Skip to content
Open
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions ts/components/ReactionPickerPicker.dom.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,19 +35,21 @@ export const ReactionPickerPickerEmojiButton = forwardRef<
return null;
}

const label = title ?? emoji;

return (
<Button
ref={ref}
className={classNames(
'module-ReactionPickerPicker__button',
'module-ReactionPickerPicker__button--emoji',
isSelected && 'module-ReactionPickerPicker__button--selected'
isSelected && 'module-ReactionPickerPicker__button--is-selected'
)}
onPress={onClick}
aria-label={label}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We actually have an API that does a better job localizing the emoji name:

aria-label={Emoji.getDisplayLabel(emoji)}

I think we can get rid of the title attribute. The aria guide for toggle buttons specify that you shouldn't change the label based on the state:

Toggle button: A two-state button that can be either off (not pressed) or on (pressed). To tell assistive technologies that a button is a toggle button, specify a value for the attribute aria-pressed. For example, a button labelled mute in an audio player could indicate that sound is muted by setting the pressed state true. Important: it is critical the label on a toggle does not change when its state changes. In this example, when the pressed state is true, the label remains "Mute" so a screen reader would say something like "Mute toggle button pressed". Alternatively, if the design were to call for the button label to change from "Mute" to "Unmute," the aria-pressed attribute would not be needed.

https://www.w3.org/WAI/ARIA/apg/patterns/button/

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the review, @jamiebuilds-signal!

  1. Regarding the emoji name localization:
    I tested using Emoji.getDisplayLabel(emoji) locally with screen readers (NVDA/JAWS), but the returned text labels are very simplified compared to delegating the raw Unicode character. For example, for the crying face emoji it announces just "llorar" (cry) instead of the full descriptive name "cara llorando", and for the red heart emoji it just says "corazón" (heart) instead of "corazón rojo" (red heart).

There is no need to worry about adding translation strings in our codebase for this: by passing the raw Unicode emoji character as the aria-label, the browser/OS delegates the translation directly to the screen reader's native CLDR engine. The screen reader automatically translates and pronounces the emoji based on the active system language of the user. I verified this behavior across multiple languages (including English, Spanish, French, Portuguese, and Italian) and it works flawlessly, sounding much more natural in every single one of them.

Therefore, I've updated the full emoji picker cells (in the "More" panel) to use the raw emoji Unicode character as well, so it matches the suggested reactions' behavior and gets the correct full screen reader name.

  1. Regarding the toggle button state:
    You are completely right. I've respected the W3C ARIA toggle button guidelines and simplified the button labels to be static (always the emoji itself), letting aria-pressed={isSelected} convey the selection/active state instead of changing the label dynamically.

I also added a check so that the long-press skin tone description ("press and hold to select skin tone") is only announced for emojis that actually support skin tone variants.

I've pushed these updates to this branch. Let me know if you have any further feedback!

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, there are definitely many cases where the official unicode title is a better accessible description of the emoji, although there are also cases where the official title doesn't really match how emojis get used by people or are wordy to the point of being disruptive in the middle of text.

There is also a gap between the languages supported by screen readers (and operating systems or the Unicode CLDR) and the languages Signal supports. Which you aren't going to see as much only looking at very broadly supported locales like English/Spanish/French/etc). Language support can also vary on different operating systems, and where possible we try to rely on our own translations because the app locale can differ from the system locale.

I am going to bring it up with our localization team to see if we could review and get accessible descriptions for every emoji. That is gonna take some time though.

In the mean time, I wonder if it would be an improvement to use the short name from Emoji.getDisplayLabel() as the aria-label and provide the emoji in aria-description to fallback to whatever Unicode name is available.

<span role="img" aria-label="heart" aria-description="❤️">❤️</span>

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ha, apparently our localization team was already working on getting translations together for the CLDR annotations dataset.

aria-pressed={isSelected}
>
<FunStaticEmoji
role="img"
aria-label={title ?? ''}
role="presentation"
size={48}
emoji={emoji}
/>
Expand Down