Use aria descriptions instead of labels for TextWithTooltip (#10952)

* Use aria descriptions instead of labels for TextWithTooltip

to prevent clobbering the reading of the content

* Update snapshot

* Fix snapshots

* Iterate

* Update snapshots

* delint
This commit is contained in:
Michael Telatynski 2023-05-25 09:42:09 +01:00 committed by GitHub
parent f4a265b2c7
commit f52fab39fc
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
23 changed files with 78 additions and 7 deletions

View file

@ -35,10 +35,6 @@ export default class TextWithTooltip extends React.Component<IProps> {
public render(): React.ReactNode {
const { class: className, children, tooltip, tooltipClass, tooltipProps, ...props } = this.props;
if (typeof tooltip === "string") {
props["aria-label"] = tooltip;
}
return (
<TooltipTarget
onClick={this.props.onClick}

View file

@ -14,13 +14,16 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import React, { forwardRef, HTMLAttributes } from "react";
import React, { forwardRef, HTMLAttributes, useRef } from "react";
import { randomString } from "matrix-js-sdk/src/randomstring";
import useFocus from "../../../hooks/useFocus";
import useHover from "../../../hooks/useHover";
import Tooltip, { ITooltipProps } from "./Tooltip";
interface IProps extends HTMLAttributes<HTMLSpanElement>, Omit<ITooltipProps, "visible"> {
interface IProps
extends HTMLAttributes<HTMLSpanElement>,
Omit<ITooltipProps, "visible" | "tabIndex" | "aria-describedby"> {
tooltipTargetClassName?: string;
ignoreHover?: (ev: React.MouseEvent) => boolean;
}
@ -46,6 +49,12 @@ const TooltipTarget = forwardRef<HTMLDivElement, IProps>(
},
ref,
) => {
const idRef = useRef("mx_TooltipTarget_" + randomString(8));
// Use generated ID if one is not passed
if (id === undefined) {
id = idRef.current;
}
const [isFocused, focusProps] = useFocus();
const [isHovering, hoverProps] = useHover(ignoreHover || (() => false));

View file

@ -56,6 +56,11 @@ import WidgetUtils from "../../../src/utils/WidgetUtils";
import { WidgetType } from "../../../src/widgets/WidgetType";
import WidgetStore from "../../../src/stores/WidgetStore";
// Fake random strings to give a predictable snapshot for IDs
jest.mock("matrix-js-sdk/src/randomstring", () => ({
randomString: () => "abdefghi",
}));
const RoomView = wrapInMatrixClientContext(_RoomView);
describe("RoomView", () => {

View file

@ -54,6 +54,7 @@ exports[`RoomView for a local room in state CREATING should match the snapshot 1
</div>
</div>
<div
aria-describedby="mx_TooltipTarget_abdefghi"
class="mx_RoomHeader_topic mx_RoomTopic"
dir="auto"
tabindex="0"
@ -146,6 +147,7 @@ exports[`RoomView for a local room in state ERROR should match the snapshot 1`]
</div>
</div>
<div
aria-describedby="mx_TooltipTarget_abdefghi"
class="mx_RoomHeader_topic mx_RoomTopic"
dir="auto"
tabindex="0"
@ -335,6 +337,7 @@ exports[`RoomView for a local room in state NEW should match the snapshot 1`] =
</div>
</div>
<div
aria-describedby="mx_TooltipTarget_abdefghi"
class="mx_RoomHeader_topic mx_RoomTopic"
dir="auto"
tabindex="0"
@ -602,6 +605,7 @@ exports[`RoomView for a local room in state NEW that is encrypted should match t
</div>
</div>
<div
aria-describedby="mx_TooltipTarget_abdefghi"
class="mx_RoomHeader_topic mx_RoomTopic"
dir="auto"
tabindex="0"

View file

@ -28,6 +28,11 @@ import {
makeRoomWithBeacons,
} from "../../../test-utils";
// Fake random strings to give a predictable snapshot for IDs
jest.mock("matrix-js-sdk/src/randomstring", () => ({
randomString: () => "abdefghi",
}));
describe("<BeaconListItem />", () => {
// 14.03.2022 16:15
const now = 1647270879403;

View file

@ -27,6 +27,11 @@ import {
mockClientMethodsUser,
} from "../../../test-utils";
// Fake random strings to give a predictable snapshot for IDs
jest.mock("matrix-js-sdk/src/randomstring", () => ({
randomString: () => "abdefghi",
}));
describe("<DialogSidebar />", () => {
const defaultProps: ComponentProps<typeof DialogSidebar> = {
beacons: [],

View file

@ -21,6 +21,11 @@ import ShareLatestLocation from "../../../../src/components/views/beacon/ShareLa
import { copyPlaintext } from "../../../../src/utils/strings";
import { flushPromises } from "../../../test-utils";
// Fake random strings to give a predictable snapshot for IDs
jest.mock("matrix-js-sdk/src/randomstring", () => ({
randomString: () => "abdefghi",
}));
jest.mock("../../../../src/utils/strings", () => ({
copyPlaintext: jest.fn().mockResolvedValue(undefined),
}));

View file

@ -32,6 +32,7 @@ exports[`<BeaconListItem /> when a beacon is live and has locations renders beac
class="mx_BeaconListItem_interactions"
>
<div
aria-describedby="mx_TooltipTarget_abdefghi"
tabindex="0"
>
<a

View file

@ -62,6 +62,7 @@ exports[`<DialogSidebar /> renders sidebar correctly with beacons 1`] = `
class="mx_BeaconListItem_interactions"
>
<div
aria-describedby="mx_TooltipTarget_abdefghi"
tabindex="0"
>
<a

View file

@ -3,6 +3,7 @@
exports[`<ShareLatestLocation /> renders share buttons when there is a location 1`] = `
<DocumentFragment>
<div
aria-describedby="mx_TooltipTarget_abdefghi"
tabindex="0"
>
<a

View file

@ -34,6 +34,7 @@ exports[`MLocationBody <MLocationBody> without error renders map correctly 1`] =
class="mx_MLocationBody"
>
<div
aria-describedby="mx_TooltipTarget_abdefghi"
tabindex="0"
>
<div
@ -66,6 +67,7 @@ exports[`MLocationBody <MLocationBody> without error renders marker correctly fo
class="mx_MLocationBody"
>
<div
aria-describedby="mx_TooltipTarget_abdefghi"
tabindex="0"
>
<div

View file

@ -36,6 +36,11 @@ import defaultDispatcher from "../../../../../src/dispatcher/dispatcher";
import { Action } from "../../../../../src/dispatcher/actions";
import MatrixClientContext from "../../../../../src/contexts/MatrixClientContext";
// Fake random strings to give a predictable snapshot for IDs
jest.mock("matrix-js-sdk/src/randomstring", () => ({
randomString: () => "abdefghi",
}));
describe("<PollHistory />", () => {
// 14.03.2022 16:15
const now = 1647270879403;

View file

@ -21,6 +21,11 @@ import { MatrixEvent } from "matrix-js-sdk/src/matrix";
import { PollListItem } from "../../../../../src/components/views/polls/pollHistory/PollListItem";
import { makePollStartEvent, mockIntlDateTimeFormat, unmockIntlDateTimeFormat } from "../../../../test-utils";
// Fake random strings to give a predictable snapshot for IDs
jest.mock("matrix-js-sdk/src/randomstring", () => ({
randomString: () => "abdefghi",
}));
describe("<PollListItem />", () => {
const event = makePollStartEvent("Question?", "@me:domain.org");
event.getContent().origin;

View file

@ -32,6 +32,11 @@ import {
unmockIntlDateTimeFormat,
} from "../../../../test-utils";
// Fake random strings to give a predictable snapshot for IDs
jest.mock("matrix-js-sdk/src/randomstring", () => ({
randomString: () => "abdefghi",
}));
describe("<PollListItemEnded />", () => {
const userId = "@alice:domain.org";
const roomId = "!room:domain.org";

View file

@ -79,6 +79,7 @@ exports[`<PollHistory /> renders a list of active polls when there are polls in
data-testid="pollListItem-$2"
>
<div
aria-describedby="mx_TooltipTarget_abdefghi"
tabindex="0"
>
<div
@ -103,6 +104,7 @@ exports[`<PollHistory /> renders a list of active polls when there are polls in
data-testid="pollListItem-$1"
>
<div
aria-describedby="mx_TooltipTarget_abdefghi"
tabindex="0"
>
<div

View file

@ -7,6 +7,7 @@ exports[`<PollListItem /> renders a poll 1`] = `
data-testid="pollListItem-$mypoll"
>
<div
aria-describedby="mx_TooltipTarget_abdefghi"
tabindex="0"
>
<div

View file

@ -7,6 +7,7 @@ exports[`<PollListItemEnded /> renders a poll with no responses 1`] = `
data-testid="pollListItem-1"
>
<div
aria-describedby="mx_TooltipTarget_abdefghi"
tabindex="0"
>
<div

View file

@ -32,6 +32,11 @@ import { getMockClientWithEventEmitter, mockClientMethodsUser } from "../../../t
import { PollHistoryDialog } from "../../../../src/components/views/dialogs/PollHistoryDialog";
import { RoomPermalinkCreator } from "../../../../src/utils/permalinks/Permalinks";
// Fake random strings to give a predictable snapshot for checkbox IDs
jest.mock("matrix-js-sdk/src/randomstring", () => ({
randomString: () => "abdefghi",
}));
describe("<RoomSummaryCard />", () => {
const userId = "@alice:domain.org";
const mockClient = getMockClientWithEventEmitter({

View file

@ -41,7 +41,7 @@ exports[`<RoomSummaryCard /> renders the room summary 1`] = `
/>
</span>
<div
aria-label="Not encrypted"
aria-describedby="mx_TooltipTarget_abdefghi"
class="mx_TextWithTooltip_target mx_RoomSummaryCard_e2ee"
tabindex="0"
/>

View file

@ -19,6 +19,11 @@ import React from "react";
import FilteredDeviceListHeader from "../../../../../src/components/views/settings/devices/FilteredDeviceListHeader";
// Fake random strings to give a predictable snapshot for IDs
jest.mock("matrix-js-sdk/src/randomstring", () => ({
randomString: () => "abdefghi",
}));
describe("<FilteredDeviceListHeader />", () => {
const defaultProps = {
selectedDeviceCount: 0,

View file

@ -7,6 +7,7 @@ exports[`<FilteredDeviceListHeader /> renders correctly when all devices are sel
data-testid="test123"
>
<div
aria-describedby="mx_TooltipTarget_abdefghi"
tabindex="0"
>
<span
@ -51,6 +52,7 @@ exports[`<FilteredDeviceListHeader /> renders correctly when no devices are sele
data-testid="test123"
>
<div
aria-describedby="mx_TooltipTarget_abdefghi"
tabindex="0"
>
<span

View file

@ -53,6 +53,11 @@ import { getClientInformationEventType } from "../../../../../../src/utils/devic
mockPlatformPeg();
// Fake random strings to give a predictable snapshot for IDs
jest.mock("matrix-js-sdk/src/randomstring", () => ({
randomString: () => "abdefghi",
}));
describe("<SessionManagerTab />", () => {
const aliceId = "@alice:server.org";
const deviceId = "alices_device";

View file

@ -328,6 +328,7 @@ exports[`<SessionManagerTab /> goes to filtered list from security recommendatio
class="mx_FilteredDeviceListHeader"
>
<div
aria-describedby="mx_TooltipTarget_abdefghi"
tabindex="0"
>
<span