fix: improve a11y of emoji list

fixes #218
release
Nolan Lawson 2019-03-09 20:57:30 -08:00
parent c2c7092fc4
commit 0f35206687
5 changed files with 30 additions and 10 deletions

View File

@ -59,6 +59,7 @@ import { Picker } from 'emoji-mart'
```js
search: 'Search',
clear: 'Clear', // Accessible label on "clear" button
emojilist: 'List of emoji', // Accessible title for list of emoji
notfound: 'No Emoji Found',
skintext: 'Choose your default skin tone',
categories: {

View File

@ -164,6 +164,11 @@
position: relative;
display: inline-block;
font-size: 0;
margin: 0;
padding: 0;
border: none;
background: none;
box-shadow: none;
}
.emoji-mart-emoji-native {

View File

@ -176,9 +176,10 @@ export default class Category extends React.Component {
}
return (
<div
<section
ref={this.setContainerRef}
className="emoji-mart-category"
aria-label={i18n.categories[id]}
style={containerStyles}
>
<div
@ -186,7 +187,11 @@ export default class Category extends React.Component {
data-name={name}
className="emoji-mart-category-label"
>
<span style={labelSpanStyles} ref={this.setLabelRef}>
<span
style={labelSpanStyles}
ref={this.setLabelRef}
aria-hidden={true /* already labeled by the section aria-label */}
>
{i18n.categories[id]}
</span>
</div>
@ -206,7 +211,7 @@ export default class Category extends React.Component {
emojiProps={emojiProps}
/>
)}
</div>
</section>
)
}
}

View File

@ -98,6 +98,12 @@ const NimbleEmoji = (props) => {
style = {},
children = props.children,
className = 'emoji-mart-emoji',
nativeEmoji = unified && unifiedToNative(unified),
// combine the emoji itself and all shortcodes into an accessible label
label = [nativeEmoji]
.concat(short_names)
.filter(Boolean)
.join(', '),
title = null
if (!unified && !custom) {
@ -115,7 +121,7 @@ const NimbleEmoji = (props) => {
if (props.native && unified) {
className += ' emoji-mart-emoji-native'
style = { fontSize: props.size }
children = unifiedToNative(unified)
children = nativeEmoji
if (props.forceSize) {
style.display = 'inline-block'
@ -173,21 +179,22 @@ const NimbleEmoji = (props) => {
if (props.html) {
style = _convertStyleToCSS(style)
return `<span style='${style}' ${
return `<button style='${style}' aria-label='${label}' ${
title ? `title='${title}'` : ''
} class='${className}'>${children || ''}</span>`
} class='${className}'>${children || ''}</button>`
} else {
return (
<span
<button
key={props.emoji.id || props.emoji}
onClick={(e) => _handleClick(e, props)}
onMouseEnter={(e) => _handleOver(e, props)}
onMouseLeave={(e) => _handleLeave(e, props)}
aria-label={label}
title={title}
className={className}
>
<span style={style}>{children}</span>
</span>
</button>
)
}
}

View File

@ -19,6 +19,7 @@ import { PickerDefaultProps } from '../../utils/shared-default-props'
const I18N = {
search: 'Search',
clear: 'Clear', // Accessible label on "clear" button
emojilist: 'List of emoji', // Accessible title for list of emoji
notfound: 'No Emoji Found',
skintext: 'Choose your default skin tone',
categories: {
@ -520,9 +521,10 @@ export default class NimblePicker extends React.PureComponent {
autoFocus={autoFocus}
/>
<div
<section
ref={this.setScrollRef}
className="emoji-mart-scroll"
aria-label={this.i18n.emojilist}
onScroll={this.handleScroll}
>
{this.getCategories().map((category, i) => {
@ -566,7 +568,7 @@ export default class NimblePicker extends React.PureComponent {
/>
)
})}
</div>
</section>
{(showPreview || showSkinTones) && (
<div className="emoji-mart-bar">