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 ```js
search: 'Search', search: 'Search',
clear: 'Clear', // Accessible label on "clear" button clear: 'Clear', // Accessible label on "clear" button
emojilist: 'List of emoji', // Accessible title for list of emoji
notfound: 'No Emoji Found', notfound: 'No Emoji Found',
skintext: 'Choose your default skin tone', skintext: 'Choose your default skin tone',
categories: { categories: {

View File

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

View File

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

View File

@ -98,6 +98,12 @@ const NimbleEmoji = (props) => {
style = {}, style = {},
children = props.children, children = props.children,
className = 'emoji-mart-emoji', 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 title = null
if (!unified && !custom) { if (!unified && !custom) {
@ -115,7 +121,7 @@ const NimbleEmoji = (props) => {
if (props.native && unified) { if (props.native && unified) {
className += ' emoji-mart-emoji-native' className += ' emoji-mart-emoji-native'
style = { fontSize: props.size } style = { fontSize: props.size }
children = unifiedToNative(unified) children = nativeEmoji
if (props.forceSize) { if (props.forceSize) {
style.display = 'inline-block' style.display = 'inline-block'
@ -173,21 +179,22 @@ const NimbleEmoji = (props) => {
if (props.html) { if (props.html) {
style = _convertStyleToCSS(style) style = _convertStyleToCSS(style)
return `<span style='${style}' ${ return `<button style='${style}' aria-label='${label}' ${
title ? `title='${title}'` : '' title ? `title='${title}'` : ''
} class='${className}'>${children || ''}</span>` } class='${className}'>${children || ''}</button>`
} else { } else {
return ( return (
<span <button
key={props.emoji.id || props.emoji} key={props.emoji.id || props.emoji}
onClick={(e) => _handleClick(e, props)} onClick={(e) => _handleClick(e, props)}
onMouseEnter={(e) => _handleOver(e, props)} onMouseEnter={(e) => _handleOver(e, props)}
onMouseLeave={(e) => _handleLeave(e, props)} onMouseLeave={(e) => _handleLeave(e, props)}
aria-label={label}
title={title} title={title}
className={className} className={className}
> >
<span style={style}>{children}</span> <span style={style}>{children}</span>
</span> </button>
) )
} }
} }

View File

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