@@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com
66Please see LICENSE files in the repository root for full details.
77*/
88
9- import React , { type JSX , type ReactNode , createRef , useCallback , useEffect , useState , useId } from "react" ;
9+ import React , { type JSX , type ReactNode , createRef , useCallback , useEffect , useState } from "react" ;
1010import EditIcon from "@vector-im/compound-design-tokens/assets/web/icons/edit" ;
1111import UploadIcon from "@vector-im/compound-design-tokens/assets/web/icons/share" ;
1212import DeleteIcon from "@vector-im/compound-design-tokens/assets/web/icons/delete" ;
@@ -89,9 +89,9 @@ interface IProps {
8989 removeAvatar ?: ( ) => void ;
9090
9191 /**
92- * The alt text for the avatar
92+ * The accessible name for the avatar, eg: "Foo's Profile Picture"
9393 */
94- avatarAltText : string ;
94+ avatarAccessibleName : string ;
9595
9696 /**
9797 * 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<HTMLInputElement>): File | n
121121 */
122122const AvatarSetting : React . FC < IProps > = ( {
123123 avatar,
124- avatarAltText ,
124+ avatarAccessibleName ,
125125 onChange,
126126 removeAvatar,
127127 disabled,
@@ -147,9 +147,6 @@ const AvatarSetting: React.FC<IProps> = ({
147147 }
148148 } , [ avatar ] ) ;
149149
150- // Prevents ID collisions when this component is used more than once on the same page.
151- const a11yId = useId ( ) ;
152-
153150 const onFileChanged = useCallback (
154151 ( e : React . ChangeEvent < HTMLInputElement > ) => {
155152 const file = getFileChanged ( e ) ;
@@ -170,48 +167,47 @@ const AvatarSetting: React.FC<IProps> = ({
170167 setMenuOpen ( newOpen ) ;
171168 } , [ ] ) ;
172169
173- let avatarElement = (
170+ const avatarElement = (
174171 < AccessibleButton
175172 element = "div"
176- onClick = { uploadAvatar }
173+ /**
174+ * This button will open a menu. That is done by passing this element as trigger
175+ * to the menu component, hence the empty onClick.
176+ */
177+ onClick = { ( ) => { } }
177178 className = "mx_AvatarSetting_avatarPlaceholder mx_AvatarSetting_avatarDisplay"
178- aria-labelledby = { disabled ? undefined : a11yId }
179- // Inhibit tab stop as we have explicit upload/remove buttons
180- tabIndex = { - 1 }
181179 disabled = { disabled }
182180 >
183- < BaseAvatar idName = { placeholderId } name = { placeholderName } size = "90px" />
181+ < BaseAvatar
182+ idName = { placeholderId }
183+ name = { placeholderName }
184+ size = "90px"
185+ url = { avatarURL }
186+ altText = { avatarAccessibleName }
187+ />
184188 </ AccessibleButton >
185189 ) ;
186- if ( avatarURL ) {
187- avatarElement = (
188- < AccessibleButton
189- element = "img"
190- className = "mx_AvatarSetting_avatarDisplay"
191- src = { avatarURL }
192- alt = { avatarAltText }
193- onClick = { uploadAvatar }
194- // Inhibit tab stop as we have explicit upload/remove buttons
195- tabIndex = { - 1 }
196- disabled = { disabled }
197- />
198- ) ;
199- }
200190
201191 let uploadAvatarBtn : JSX . Element | undefined ;
202192 if ( ! disabled ) {
203193 const uploadButtonClasses = classNames ( "mx_AvatarSetting_uploadButton" , {
204194 mx_AvatarSetting_uploadButton_active : menuOpen ,
205195 } ) ;
206196 uploadAvatarBtn = (
207- < div className = { uploadButtonClasses } >
208- < EditIcon width = "20px" height = "20px" />
197+ < div
198+ className = { uploadButtonClasses }
199+ role = "button"
200+ aria-label = { _t ( "settings|general|avatar_open_menu" ) }
201+ tabIndex = { 0 }
202+ aria-haspopup = "menu"
203+ >
204+ < EditIcon aria-hidden = { true } width = "20px" height = "20px" />
209205 </ div >
210206 ) ;
211207 }
212208
213209 const content = (
214- < div className = "mx_AvatarSetting_avatar" role = "group" aria-label = { avatarAltText } >
210+ < div className = "mx_AvatarSetting_avatar" role = "group" aria-label = { avatarAccessibleName } >
215211 { avatarElement }
216212 { uploadAvatarBtn }
217213 </ div >
0 commit comments