diff --git a/src/components/views/room_settings/RoomProfileSettings.tsx b/src/components/views/room_settings/RoomProfileSettings.tsx index e7674a109a..ea727122b2 100644 --- a/src/components/views/room_settings/RoomProfileSettings.tsx +++ b/src/components/views/room_settings/RoomProfileSettings.tsx @@ -262,7 +262,7 @@ export default class RoomProfileSettings extends React.Component ? undefined : (this.state.avatarFile ?? this.state.originalAvatarUrl ?? undefined) } - avatarAltText={_t("room_settings|general|avatar_field_label")} + avatarAccessibleName={_t("room_settings|general|avatar_field_label")} disabled={!this.state.canSetAvatar} onChange={this.onAvatarChanged} removeAvatar={canRemove ? this.removeAvatar : undefined} diff --git a/src/components/views/settings/AvatarSetting.tsx b/src/components/views/settings/AvatarSetting.tsx index 9992e3691b..2c8dac96d7 100644 --- a/src/components/views/settings/AvatarSetting.tsx +++ b/src/components/views/settings/AvatarSetting.tsx @@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com Please see LICENSE files in the repository root for full details. */ -import React, { type JSX, type ReactNode, createRef, useCallback, useEffect, useState, useId } from "react"; +import React, { type JSX, type ReactNode, createRef, useCallback, useEffect, useState } from "react"; import EditIcon from "@vector-im/compound-design-tokens/assets/web/icons/edit"; import UploadIcon from "@vector-im/compound-design-tokens/assets/web/icons/share"; import DeleteIcon from "@vector-im/compound-design-tokens/assets/web/icons/delete"; @@ -89,9 +89,9 @@ interface IProps { removeAvatar?: () => void; /** - * The alt text for the avatar + * The accessible name for the avatar, eg: "Foo's Profile Picture" */ - avatarAltText: string; + avatarAccessibleName: string; /** * String to use for computing the colour of the placeholder avatar if no avatar is set @@ -121,7 +121,7 @@ export function getFileChanged(e: React.ChangeEvent): File | n */ const AvatarSetting: React.FC = ({ avatar, - avatarAltText, + avatarAccessibleName, onChange, removeAvatar, disabled, @@ -147,9 +147,6 @@ const AvatarSetting: React.FC = ({ } }, [avatar]); - // Prevents ID collisions when this component is used more than once on the same page. - const a11yId = useId(); - const onFileChanged = useCallback( (e: React.ChangeEvent) => { const file = getFileChanged(e); @@ -170,33 +167,26 @@ const AvatarSetting: React.FC = ({ setMenuOpen(newOpen); }, []); - let avatarElement = ( + const avatarElement = ( {}} className="mx_AvatarSetting_avatarPlaceholder mx_AvatarSetting_avatarDisplay" - aria-labelledby={disabled ? undefined : a11yId} - // Inhibit tab stop as we have explicit upload/remove buttons - tabIndex={-1} disabled={disabled} > - + ); - if (avatarURL) { - avatarElement = ( - - ); - } let uploadAvatarBtn: JSX.Element | undefined; if (!disabled) { @@ -204,14 +194,20 @@ const AvatarSetting: React.FC = ({ mx_AvatarSetting_uploadButton_active: menuOpen, }); uploadAvatarBtn = ( -
- +
+
); } const content = ( -
+
{avatarElement} {uploadAvatarBtn}
diff --git a/src/components/views/settings/UserProfileSettings.tsx b/src/components/views/settings/UserProfileSettings.tsx index 4590f948ef..86e77b6b47 100644 --- a/src/components/views/settings/UserProfileSettings.tsx +++ b/src/components/views/settings/UserProfileSettings.tsx @@ -203,7 +203,7 @@ const UserProfileSettings: React.FC = ({
", () => { stubClient(); }); - it("renders avatar with specified alt text", async () => { - const { queryByAltText } = render( + it("renders avatar with specified accessible name", async () => { + const { getByRole } = render( , ); - const imgElement = queryByAltText("Avatar of Peter Fox"); - expect(imgElement).toBeInTheDocument(); + const avatarButton = getByRole("button", { name: "Avatar of Peter Fox" }); + expect(avatarButton).toBeInTheDocument(); }); it("renders a file as the avatar when supplied", async () => { @@ -44,12 +44,13 @@ describe("", () => { , ); - const imgElement = await screen.findByRole("button", { name: "Avatar of Peter Fox" }); + const avatarButton = await screen.findByRole("button", { name: "Avatar of Peter Fox" }); + const imgElement = avatarButton.querySelector("img"); expect(imgElement).toBeInTheDocument(); expect(imgElement).toHaveAttribute("src", "data:image/gif;base64," + BASE64_GIF); }); @@ -63,7 +64,7 @@ describe("", () => { placeholderId="blee" placeholderName="boo" avatar="mxc://example.org/my-avatar" - avatarAltText="Avatar of Peter Fox" + avatarAccessibleName="Avatar of Peter Fox" onChange={onChange} />, ); @@ -82,7 +83,7 @@ describe("", () => { placeholderId="blee" placeholderName="boo" avatar="mxc://example.org/my-avatar" - avatarAltText="Avatar of Peter Fox" + avatarAccessibleName="Avatar of Peter Fox" onChange={onChange} />, ); @@ -102,7 +103,7 @@ describe("", () => { placeholderId="blee" placeholderName="boo" avatar="mxc://example.org/my-avatar" - avatarAltText="Avatar of Peter Fox" + avatarAccessibleName="Avatar of Peter Fox" onChange={onChange} />, );