[MM-61604]: Fixed aria-expanded not correctly announced by screen reader (#30262)

* [MM-61604]: Fixed aria-expanded not correctly announced by screen reader

* [MM-61604]: Translation changes
Этот коммит содержится в:
ayush-chauhan233
2025-03-10 20:38:57 +05:30
коммит произвёл GitHub
родитель c5e6d9f570
Коммит 2cb8d65522
2 изменённых файлов: 74 добавлений и 66 удалений

Просмотреть файл

@@ -112,12 +112,62 @@ export class EmojiPickerSkin extends React.PureComponent<Props, State> {
this.setState({pickerExtended: true});
};
extended() {
skinTonePickerButton() {
const {pickerExtended} = this.state;
const expandButtonLabel = this.props.intl.formatMessage({
id: 'emoji_picker.skin_tone',
defaultMessage: 'Skin tone',
});
const closeButtonLabel = this.props.intl.formatMessage({
id: 'emoji_skin.close',
defaultMessage: 'Close skin tones',
});
const choices = skinTones.map((skinTone) => {
const emoji = skinTones.find(({value}) => value === this.props.userSkinTone)!.emoji;
const buttonClassName = classNames('style--none', {'skin-tones__close-icon': pickerExtended, 'skin-tones__icon skin-tones__expand-icon': !pickerExtended});
const spriteClassName = classNames('emojisprite', `emoji-category-${emoji?.category}`, `emoji-${emoji?.unified.toLowerCase()}`);
const handleOnClick = () => {
if (pickerExtended) {
this.hideSkinTonePicker(this.props.userSkinTone);
} else {
this.showSkinTonePicker();
}
};
return (
<button
className={buttonClassName}
onClick={handleOnClick}
aria-expanded={pickerExtended}
aria-label={pickerExtended ? closeButtonLabel : expandButtonLabel}
aria-controls='skin-tones-icons'
data-testid={pickerExtended === false ? `skin-picked-${this.props.userSkinTone}` : undefined}
>
{pickerExtended ? (
<CloseIcon
size={16}
color={'rgba(var(--center-channel-color-rgb), 0.75)'}
/>
) : (
<WithTooltip
title={expandButtonLabel}
>
<img
alt={'emoji skin tone picker'}
src={imgTrans}
className={spriteClassName}
/>
</WithTooltip>
)}
</button>
);
}
choices() {
return skinTones.map((skinTone) => {
const skin = skinTone.value;
const emoji = skinTone.emoji;
const spriteClassName = classNames('emojisprite', `emoji-category-${emoji.category}`, `emoji-${emoji.unified.toLowerCase()}`);
@@ -138,68 +188,6 @@ export class EmojiPickerSkin extends React.PureComponent<Props, State> {
</button>
);
});
return (
<>
<div className='skin-tones__close'>
<button
className='skin-tones__close-icon style--none'
onClick={() => this.hideSkinTonePicker(this.props.userSkinTone)}
aria-label={closeButtonLabel}
aria-expanded={this.state.pickerExtended}
tabIndex={0}
aria-controls='skin-tones-icons'
>
<CloseIcon
size={16}
color={'rgba(var(--center-channel-color-rgb), 0.75)'}
/>
</button>
<div className='skin-tones__close-text'>
<FormattedMessage
{...skinTones[skinTones.length - 1].label}
/>
</div>
</div>
<div
className='skin-tones__icons'
id='skin-tones-icons'
aria-label='Skin tone icons'
role='region'
>
{choices}
</div>
</>
);
}
collapsed() {
const emoji = skinTones.find(({value}) => value === this.props.userSkinTone)!.emoji;
const spriteClassName = classNames('emojisprite', `emoji-category-${emoji?.category}`, `emoji-${emoji?.unified.toLowerCase()}`);
const expandButtonLabel = this.props.intl.formatMessage({
id: 'emoji_picker.skin_tone',
defaultMessage: 'Skin tone',
});
return (
<WithTooltip
title={expandButtonLabel}
>
<button
data-testid={`skin-picked-${this.props.userSkinTone}`}
className='style--none skin-tones__icon skin-tones__expand-icon'
onClick={this.showSkinTonePicker}
aria-label={expandButtonLabel}
aria-controls='skin-tones-icons'
aria-expanded={this.state.pickerExtended}
>
<img
alt={'emoji skin tone picker'}
src={imgTrans}
className={spriteClassName}
/>
</button>
</WithTooltip>
);
}
render() {
@@ -211,10 +199,29 @@ export class EmojiPickerSkin extends React.PureComponent<Props, State> {
>
<div className={classNames('skin-tones', {'skin-tones--active': this.state.pickerExtended})}>
<div
className={classNames('skin-tones__content', {'skin-tones__content__single': !this.state.pickerExtended})}
className={classNames('skin-tones__content', {'skin-tones__content__single': !this.state.pickerExtended}, {'skin-tones__close': this.state.pickerExtended})}
aria-orientation='horizontal'
>
{this.state.pickerExtended ? this.extended() : this.collapsed() }
{this.skinTonePickerButton()}
{this.state.pickerExtended &&
<>
<div className='skin-tones__close-text'>
<FormattedMessage
{...skinTones[skinTones.length - 1].label}
/>
</div>
<div
className='skin-tones__icons'
id='skin-tones-icons'
aria-label={this.props.intl.formatMessage({
id: 'emoji_picker.skin_tone_icons',
defaultMessage: 'Skin tone icons',
})}
role='region'
>
{this.choices()}
</div>
</>}
</div>
</div>
</CSSTransition>

Просмотреть файл

@@ -3745,6 +3745,7 @@
"emoji_picker.search_emoji": "Search for an emoji",
"emoji_picker.searchResults": "Search Results",
"emoji_picker.skin_tone": "Skin tone",
"emoji_picker.skin_tone_icons": "Skin tone icons",
"emoji_picker.smileys-emotion": "Smileys & Emotion",
"emoji_picker.symbols": "Symbols",
"emoji_picker.travel-places": "Travel Places",