[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
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
c5e6d9f570
Коммит
2cb8d65522
@@ -112,12 +112,62 @@ export class EmojiPickerSkin extends React.PureComponent<Props, State> {
|
|||||||
this.setState({pickerExtended: true});
|
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({
|
const closeButtonLabel = this.props.intl.formatMessage({
|
||||||
id: 'emoji_skin.close',
|
id: 'emoji_skin.close',
|
||||||
defaultMessage: 'Close skin tones',
|
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 skin = skinTone.value;
|
||||||
const emoji = skinTone.emoji;
|
const emoji = skinTone.emoji;
|
||||||
const spriteClassName = classNames('emojisprite', `emoji-category-${emoji.category}`, `emoji-${emoji.unified.toLowerCase()}`);
|
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>
|
</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() {
|
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', {'skin-tones--active': this.state.pickerExtended})}>
|
||||||
<div
|
<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'
|
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>
|
||||||
</div>
|
</div>
|
||||||
</CSSTransition>
|
</CSSTransition>
|
||||||
|
|||||||
@@ -3745,6 +3745,7 @@
|
|||||||
"emoji_picker.search_emoji": "Search for an emoji",
|
"emoji_picker.search_emoji": "Search for an emoji",
|
||||||
"emoji_picker.searchResults": "Search Results",
|
"emoji_picker.searchResults": "Search Results",
|
||||||
"emoji_picker.skin_tone": "Skin tone",
|
"emoji_picker.skin_tone": "Skin tone",
|
||||||
|
"emoji_picker.skin_tone_icons": "Skin tone icons",
|
||||||
"emoji_picker.smileys-emotion": "Smileys & Emotion",
|
"emoji_picker.smileys-emotion": "Smileys & Emotion",
|
||||||
"emoji_picker.symbols": "Symbols",
|
"emoji_picker.symbols": "Symbols",
|
||||||
"emoji_picker.travel-places": "Travel Places",
|
"emoji_picker.travel-places": "Travel Places",
|
||||||
|
|||||||
Ссылка в новой задаче
Block a user