Accessibility Support in Enact
We recognize that applications built using our framework should be usable by anyone regardless of ability. As a result, accessibility has been a key concern for Enact since inception.
Roles
Many of our components replace native implementations with styled, feature-filled alternatives. In some cases, this means that we lose some of the native semantic meaning and accessibility. Fortunately, this can be solved by assigning ARIA roles to those custom components. When possible, we’ve assigned the relevant role to each of our custom components but that can be overridden by users, if needed.
import CheckboxItem from '@enact/moonstone/CheckboxItem';
import React from 'react';
const App = (props) => {
return (
<div {...props}>
/* Renders a CheckboxItem with the default role, checkbox */
<CheckboxItem>Sign me up for Enact news!</CheckboxItem>
/* Renders a CheckboxItem with the custom role, menuitemcheckbox */
<CheckboxItem role="menuitemcheckbox">Sign me up for Enact news!</CheckboxItem>
</div>
);
};
Attributes
There are also a set of ARIA attributes that reflect the current state of a component such as aria-checked
for a checkbox or aria-valuetext
for a slider. In these cases, Enact will map the public prop (e.g. selected
or value
) to the appropriate ARIA attribute.
In
@enact/moonstone
, some components include additional ARIA configurations specific to webOS. Those may be (or may soon be) overridden by consumers to suit their own requirements.
Custom Components
We’ve included a few custom components that may be useful to build accessible applications. None are required but provide some syntactic sugar ease development.
moonstone/Region
moonstone/Region provides a labeled region to group components. The title
is wrapped by a moonstone/Divider to provide visual context to the children
. The Divider and children
are wrapped by a <div role="region">
with its aria-label
set to the title
to provide aural context.
import Region from '@enact/moonstone/Region';
import CheckboxItem from '@enact/moonstone/CheckboxItem';
import Group from '@enact/ui/Group';
import React from 'react';
const App = () => {
return (
<Region title="Select an Option">
<Group childComponent={CheckboxItem} selectedProp="selected">
{items}
</Group>
</Region>
);
};
ui/A11yDecorator
ui/A11yDecorator is a Higher-Order Component that helps provide constant hint text to precede or follow the aria-label
for a component. This is most useful in cases where the aria-label
changes but the content before or after it is constant.
import A11yDecorator from '@enact/ui/A11yDecorator';
import CustomComponent from './components/CustomComponent';
const Component = A11yDecorator(CustomComponent);
const App = (props) => {
return (
/*
* passes aria-label to CustomComponent with accessibilityPreHint, props.label, and
* accessibiltyHint joined together with spaces
*/
<Component
accessibilityPreHint="before text"
aria-label={props.label}
accessibilityHint="after text"
/>
);
};
ui/AnnounceDecorator
ui/AnnounceDecorator provides a Higher-Order Component that adds the ability for the Wrapped component to notify the user of a state change. It provides a callback to the Wrapped component that can be called with a string which is inserted into a node with the alert
role to notify the user.
import AnnounceDecorator from '@enact/ui/AnnounceDecorator';
import React from 'react';
const ExampleComponentBase = class extends React.Component {
static propTypes = {
// passed by AnnounceDecorator
announce: PropTypes.func
}
notify = () => {
const {announce} = this.props;
announce('this text will be alerted to user by TTS');
}
render () {
<div>
<button onClick={this.notify}>Notify on Click</button>
</div>
}
};
const ExampleComponent = AnnounceDecorator(ExampleComponentBase);
const App = (props) => {
return (
/* when clicked, the user will be alerted with 'this text will be alerted to user by TTS' */
<ExampleComponent />
);
};