From 3b848fe3783fc6aa49505f24d73ca48a73b5e9b6 Mon Sep 17 00:00:00 2001 From: Nicolas Gallagher Date: Tue, 8 Sep 2015 00:09:09 -0700 Subject: [PATCH] View: additional accessibility props * Add `accessibilityLiveRegion` for `aria-live` support. * Add `accessibilityRole` for `role` support. Fix #11 --- docs/components/View.md | 28 ++++++++++++++++++++++++---- example/example.js | 2 +- src/components/View/index.js | 23 ++++++++++++++++------- src/components/View/index.spec.js | 8 ++++++++ src/modules/specHelpers/index.js | 20 ++++++++++++++++++++ src/modules/styles/styles.css | 4 ++++ 6 files changed, 73 insertions(+), 12 deletions(-) diff --git a/docs/components/View.md b/docs/components/View.md index f057e2b1..c3337103 100644 --- a/docs/components/View.md +++ b/docs/components/View.md @@ -10,17 +10,37 @@ NOTE: `View` will transfer all other props to the rendered HTML element. **accessibilityLabel** string -Overrides the text that's read by the screen reader when the user interacts -with the element. (This is implemented using `aria-label`.) +Defines the text available to assistive technologies upon interaction with the +element. (This is implemented using `aria-label`.) **accessible** bool -When `false`, the view is hidden from screenreaders. Default: `true`. (This is +When `false`, the view is hidden from assistive technologies. Default: `true`. (This is implemented using `aria-hidden`.) +**accessibilityLiveRegion** oneOf('assertive', 'off', 'polite') + +Indicates to assistive technologies whether to notify the user when the view +changes. The values of this attribute are expressed in degrees of importance. +When regions are specified as `polite` (recommended), updates take low +priority. When regions are specified as `assertive`, assistive technologies +will interrupt and immediately notify the user. Default: `off`. (This is +implemented using [`aria-live`](http://www.w3.org/TR/wai-aria/states_and_properties#aria-live).) + +**accessibilityRole** oneOf(roles) + +Allows assistive technologies to present and support interaction with the view +in a manner that is consistent with user expectations for similar views of that +type. For example, marking a touchable view with an `accessibilityRole` of +`button`. (This is implemented using [ARIA roles](http://www.w3.org/TR/wai-aria/roles#role_definitions)). + +Note: Avoid changing `accessibilityRole` values over time or after user +actions. Generally, accessibility APIs do not provide a means of notifying +assistive technologies of a `role` value change. + **component** function, string -Default: `div`. +The React Component for this view. Default: `div`. **pointerEvents** oneOf('auto', 'box-only', 'box-none', 'none') diff --git a/example/example.js b/example/example.js index 6400c91a..e56ef3f5 100644 --- a/example/example.js +++ b/example/example.js @@ -53,7 +53,7 @@ class Example extends Component { render() { return ( - + React Native for Web: examples Image diff --git a/src/components/View/index.js b/src/components/View/index.js index 1c7c6fae..6e9a85a3 100644 --- a/src/components/View/index.js +++ b/src/components/View/index.js @@ -31,15 +31,12 @@ const styles = { class View extends React.Component { static propTypes = { accessibilityLabel: PropTypes.string, + accessibilityLiveRegion: PropTypes.oneOf(['assertive', 'off', 'polite']), + accessibilityRole: PropTypes.string, accessible: PropTypes.bool, children: PropTypes.any, component: CoreComponent.propTypes.component, - pointerEvents: PropTypes.oneOf([ - 'auto', - 'box-none', - 'box-only', - 'none' - ]), + pointerEvents: PropTypes.oneOf(['auto', 'box-none', 'box-only', 'none']), style: PropTypes.shape(ViewStylePropTypes), testID: CoreComponent.propTypes.testID } @@ -53,7 +50,17 @@ class View extends React.Component { } render() { - const { accessible, accessibilityLabel, pointerEvents, style, testID, ...other } = this.props + const { + accessibilityLabel, + accessibilityLiveRegion, + accessibilityRole, + accessible, + pointerEvents, + style, + testID, + ...other + } = this.props + const pointerEventsStyle = pointerEvents && { pointerEvents } const resolvedStyle = pickProps(style, viewStyleKeys) @@ -62,7 +69,9 @@ class View extends React.Component { {...other} aria-hidden={accessible ? null : true} aria-label={accessibilityLabel} + aria-live={accessibilityLiveRegion} className={'View'} + role={accessibilityRole} style={{ ...(styles.initial), ...resolvedStyle, diff --git a/src/components/View/index.spec.js b/src/components/View/index.spec.js index 777f2033..125b765c 100644 --- a/src/components/View/index.spec.js +++ b/src/components/View/index.spec.js @@ -11,6 +11,14 @@ suite('View', () => { assertProps.accessibilityLabel(View) }) + test('prop "accessibilityLiveRegion"', () => { + assertProps.accessibilityLiveRegion(View) + }) + + test('prop "accessibilityRole"', () => { + assertProps.accessibilityRole(View) + }) + test('prop "accessible"', () => { assertProps.accessible(View) }) diff --git a/src/modules/specHelpers/index.js b/src/modules/specHelpers/index.js index d1f22424..3a115bb9 100644 --- a/src/modules/specHelpers/index.js +++ b/src/modules/specHelpers/index.js @@ -14,6 +14,26 @@ export const assertProps = { assert.equal(dom.getAttribute('aria-label'), accessibilityLabel) }, + accessibilityLiveRegion: function (Component) { + // no live + let dom = renderToDOM() + assert.equal(dom.getAttribute('aria-live'), null) + // with live + const accessibilityLiveRegion = 'polite' + dom = renderToDOM() + assert.equal(dom.getAttribute('aria-live'), accessibilityLiveRegion) + }, + + accessibilityRole: function (Component) { + // no role + let dom = renderToDOM() + assert.equal(dom.getAttribute('role'), null) + // with role + const accessibilityRole = 'main' + dom = renderToDOM() + assert.equal(dom.getAttribute('role'), accessibilityRole) + }, + accessible: function (Component) { // accessible let dom = renderToDOM() diff --git a/src/modules/styles/styles.css b/src/modules/styles/styles.css index ebab49ee..a7126002 100644 --- a/src/modules/styles/styles.css +++ b/src/modules/styles/styles.css @@ -245,6 +245,10 @@ .color-inherit { color: inherit; } .color-transparent { color: transparent; } +/* cursor */ + +.cursor-pointer { cursor: pointer; } + /* direction */ .direction-inherit { direction: inherit; }