diff --git a/docs/guides/accessibility.md b/docs/guides/accessibility.md
index 518b36b02..b1f971ec1 100644
--- a/docs/guides/accessibility.md
+++ b/docs/guides/accessibility.md
@@ -35,6 +35,34 @@ using `aria-label`.
```
+### accessibilityLiveRegion
+
+When components dynamically change we may need to inform the user. The
+`accessibilityLiveRegion` property serves this purpose and can be set to
+`none`, `polite` and `assertive`. On web, `accessibilityLiveRegion` is
+implemented using `aria-live`.
+
+* `none`: Accessibility services should not announce changes to this view.
+* `polite`: Accessibility services should announce changes to this view.
+* `assertive`: Accessibility services should interrupt ongoing speech to immediately announce changes to this view.
+
+```
+
+
+ Click me
+
+
+
+
+ Clicked {this.state.count} times
+
+```
+
+In the above example, method `_addOne` changes the `state.count` variable. As
+soon as an end user clicks the `TouchableWithoutFeedback`, screen readers
+announce text in the `Text` view because of its
+`accessibilityLiveRegion="polite"` property.
+
### accessibilityRole
In some cases, we also want to alert the end user of the type of selected
@@ -49,7 +77,8 @@ element][html-aria-url] and ARIA `role`, where possible. In most cases, both
the element and ARIA `role` are rendered. While this may contradict some ARIA
recommendations, it also helps avoid certain browser bugs, HTML5 conformance
errors, and accessibility anti-patterns (e.g., giving a `heading` role to a
-`button` element).
+`button` element). On the Web, `accessibilityRole` supports more values than
+React Native does for [Andriod and iOS](https://facebook.github.io/react-native/docs/accessibility#accessibilityrole-ios-android).
Straight-forward examples:
@@ -85,33 +114,12 @@ 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.
-### accessibilityLiveRegion
-
-When components dynamically change we may need to inform the user. The
-`accessibilityLiveRegion` property serves this purpose and can be set to
-`none`, `polite` and `assertive`. On web, `accessibilityLiveRegion` is
-implemented using `aria-live`.
-
-* `none`: Accessibility services should not announce changes to this view.
-* `polite`: Accessibility services should announce changes to this view.
-* `assertive`: Accessibility services should interrupt ongoing speech to immediately announce changes to this view.
+### accessibilityStates
-```
-
-
- Click me
-
-
-
-
- Clicked {this.state.count} times
-
-```
-
-In the above example, method `_addOne` changes the `state.count` variable. As
-soon as an end user clicks the `TouchableWithoutFeedback`, screen readers
-announce text in the `Text` view because of its
-`accessibilityLiveRegion="polite"` property.
+The `accessibilityStates` prop is an array of values used to infer the
+analogous ARIA states, e.g., `aria-disabled`, `aria-pressed`, `aria-selected`.
+On the Web, `accessibilityStates` supports more values than React Native does
+for [Andriod and iOS](https://facebook.github.io/react-native/docs/accessibility#accessibilitystate-ios-android).
### importantForAccessibility
diff --git a/packages/react-native-web/src/exports/View/ViewPropTypes.js b/packages/react-native-web/src/exports/View/ViewPropTypes.js
index 2d36c910c..5683360b0 100644
--- a/packages/react-native-web/src/exports/View/ViewPropTypes.js
+++ b/packages/react-native-web/src/exports/View/ViewPropTypes.js
@@ -11,7 +11,7 @@
import EdgeInsetsPropType, { type EdgeInsetsProp } from '../EdgeInsetsPropType';
import StyleSheetPropType from '../../modules/StyleSheetPropType';
import ViewStylePropTypes from './ViewStylePropTypes';
-import { any, array, bool, func, object, oneOf, oneOfType, string } from 'prop-types';
+import { any, array, arrayOf, bool, func, object, oneOf, oneOfType, string } from 'prop-types';
const stylePropType = StyleSheetPropType(ViewStylePropTypes);
@@ -33,6 +33,7 @@ export type ViewProps = {
accessibilityLabel?: string,
accessibilityLiveRegion?: 'none' | 'polite' | 'assertive',
accessibilityRole?: string,
+ accessibilityStates?: Array,
accessibilityTraits?: string | Array,
accessible?: boolean,
children?: any,
@@ -83,6 +84,17 @@ const ViewPropTypes = {
accessibilityLabel: string,
accessibilityLiveRegion: oneOf(['assertive', 'none', 'polite']),
accessibilityRole: string,
+ accessibilityStates: arrayOf(oneOf([
+ 'disabled',
+ 'selected',
+ /* web-only */
+ 'busy',
+ 'checked',
+ 'expanded',
+ 'grabbed',
+ 'invalid',
+ 'pressed'
+ ])),
accessibilityTraits: oneOfType([array, string]),
accessible: bool,
children: any,
diff --git a/packages/react-native-web/src/exports/View/filterSupportedProps.js b/packages/react-native-web/src/exports/View/filterSupportedProps.js
index 41c718446..5f5a763c9 100644
--- a/packages/react-native-web/src/exports/View/filterSupportedProps.js
+++ b/packages/react-native-web/src/exports/View/filterSupportedProps.js
@@ -1,8 +1,9 @@
-const whitelist = {
+const supportedProps = {
accessibilityComponentType: true,
accessibilityLabel: true,
accessibilityLiveRegion: true,
accessibilityRole: true,
+ accessibilityStates: true,
accessibilityTraits: true,
accessible: true,
children: true,
@@ -67,7 +68,7 @@ const filterSupportedProps = props => {
const safeProps = {};
for (const prop in props) {
if (props.hasOwnProperty(prop)) {
- if (whitelist[prop] || prop.indexOf('aria-') === 0 || prop.indexOf('data-') === 0) {
+ if (supportedProps[prop] || prop.indexOf('aria-') === 0 || prop.indexOf('data-') === 0) {
safeProps[prop] = props[prop];
}
}
diff --git a/packages/react-native-web/src/modules/AccessibilityUtil/__tests__/propsToAriaRole-test.js b/packages/react-native-web/src/modules/AccessibilityUtil/__tests__/propsToAriaRole-test.js
index cab195655..0685c1457 100644
--- a/packages/react-native-web/src/modules/AccessibilityUtil/__tests__/propsToAriaRole-test.js
+++ b/packages/react-native-web/src/modules/AccessibilityUtil/__tests__/propsToAriaRole-test.js
@@ -25,4 +25,11 @@ describe('modules/AccessibilityUtil/propsToAriaRole', () => {
})
).toEqual('link');
});
+
+ test('when "accessibilityRole" is a native-only value', () => {
+ expect(propsToAriaRole({ accessibilityRole: 'none' })).toEqual('presentation');
+ expect(propsToAriaRole({ accessibilityRole: 'imagebutton' })).toEqual(undefined);
+ // not really native-only, but used to allow Web to render