[change] Remove 'accessibilityRelationship'; add 'dataSet'

Remove the 'accessibilityRelationship' prop which is not part of React Native.
The general approach to supporting ARIA-like accessibility APIs in React Native
needs revisiting and it will be easier to stop going down this path.

This patch also reverts the "unstable_ariaSet" change, and renames
"unstable_dataSet" to "dataSet". Avoiding another breaking change to
accessibility props will ease upgrading for now.
This commit is contained in:
Nicolas Gallagher
2020-05-27 14:35:41 -07:00
parent 972317c17c
commit 5dda71c2a6
16 changed files with 24 additions and 126 deletions
@@ -14,7 +14,6 @@ some props are exclusive to or excluded from `multiline`.
| Name | Type | Default |
| ------------------------- | --------- | ------- |
| accessibilityLabel | ?string | |
| accessibilityRelationship | ?Object | |
| accessibilityState | ?Object | |
| autoCapitalize | ?string | 'sentences' |
| autoComplete | ?string | 'on' |
@@ -17,7 +17,6 @@ Please also refer to the in-depth "Accessibility" and "Style" guides.
| ------------------------- | --------- | ------- |
| accessibilityLabel | ?string | |
| accessibilityLiveRegion | ?string | |
| accessibilityRelationship | ?Object | |
| accessibilityRole | ?string | |
| accessibilityState | ?Object | |
| accessibilityValue | ?Object | |
@@ -44,10 +44,6 @@ announce the change. (This is implemented using `aria-live`.)
</Text>
```
### accessibilityRelationship: ?object
...
### accessibilityRole: ?string
Indicates to assistive technologies how to describe the view, e.g., that it is a "button".
-2
View File
@@ -136,7 +136,6 @@ function resolveAssetUri(source): ?string {
const Image = forwardRef<ImageProps, *>((props, ref) => {
const {
accessibilityLabel,
accessibilityRelationship,
accessibilityRole,
accessibilityState,
accessible,
@@ -276,7 +275,6 @@ const Image = forwardRef<ImageProps, *>((props, ref) => {
return (
<View
accessibilityLabel={accessibilityLabel}
accessibilityRelationship={accessibilityRelationship}
accessibilityRole={accessibilityRole}
accessibilityState={accessibilityState}
accessible={accessible}
@@ -73,7 +73,6 @@ function shouldEmitScrollEvent(lastTick: number, eventThrottle: number) {
const ScrollViewBase = forwardRef<Props, *>((props, forwardedRef) => {
const {
accessibilityLabel,
accessibilityRelationship,
accessibilityRole,
accessibilityState,
children,
@@ -146,7 +145,6 @@ const ScrollViewBase = forwardRef<Props, *>((props, forwardedRef) => {
return (
<View
accessibilityLabel={accessibilityLabel}
accessibilityRelationship={accessibilityRelationship}
accessibilityRole={accessibilityRole}
accessibilityState={accessibilityState}
children={children}
+2 -4
View File
@@ -25,7 +25,6 @@ import TextAncestorContext from './TextAncestorContext';
const forwardPropsList = {
accessibilityLabel: true,
accessibilityLiveRegion: true,
accessibilityRelationship: true,
accessibilityRole: true,
accessibilityState: true,
accessibilityValue: true,
@@ -56,6 +55,7 @@ const forwardPropsList = {
style: true,
testID: true,
// unstable
dataSet: true,
onMouseDown: true,
onMouseEnter: true,
onMouseLeave: true,
@@ -67,9 +67,7 @@ const forwardPropsList = {
onWheel: true,
href: true,
rel: true,
target: true,
unstable_ariaSet: true,
unstable_dataSet: true
target: true
};
const pickProps = props => pick(props, forwardPropsList);
-9
View File
@@ -63,15 +63,6 @@ export type TextStyle = {
export type TextProps = {
...ViewProps,
accessibilityRelationship?: {
activedescendant?: ?string,
controls?: ?string,
describedby?: ?string,
details?: ?string,
haspopup?: ?string,
labelledby?: ?string,
owns?: ?string
},
accessibilityRole?:
| 'button'
| 'header'
+2 -4
View File
@@ -48,7 +48,6 @@ const setSelection = (node, selection) => {
const forwardPropsList = {
accessibilityLabel: true,
accessibilityLiveRegion: true,
accessibilityRelationship: true,
accessibilityRole: true,
accessibilityState: true,
accessibilityValue: true,
@@ -91,15 +90,14 @@ const forwardPropsList = {
testID: true,
type: true,
// unstable
dataSet: true,
onMouseDown: true,
onMouseEnter: true,
onMouseLeave: true,
onMouseMove: true,
onMouseOver: true,
onMouseOut: true,
onMouseUp: true,
unstable_ariaSet: true,
unstable_dataSet: true
onMouseUp: true
};
const pickProps = props => pick(props, forwardPropsList);
+2 -4
View File
@@ -25,7 +25,6 @@ import TextAncestorContext from '../Text/TextAncestorContext';
const forwardPropsList = {
accessibilityLabel: true,
accessibilityLiveRegion: true,
accessibilityRelationship: true,
accessibilityRole: true,
accessibilityState: true,
accessibilityValue: true,
@@ -55,6 +54,7 @@ const forwardPropsList = {
style: true,
testID: true,
// unstable
dataSet: true,
onMouseDown: true,
onMouseEnter: true,
onMouseLeave: true,
@@ -66,9 +66,7 @@ const forwardPropsList = {
onWheel: true,
href: true,
rel: true,
target: true,
unstable_ariaSet: true,
unstable_dataSet: true
target: true
};
const pickProps = props => pick(props, forwardPropsList);
+2 -12
View File
@@ -61,15 +61,6 @@ export type ViewStyle = {
export type ViewProps = {
accessibilityLabel?: ?string,
accessibilityLiveRegion?: 'none' | 'polite' | 'assertive',
accessibilityRelationship?: {
activedescendant?: ?string,
controls?: ?string,
describedby?: ?string,
details?: ?string,
haspopup?: ?string,
labelledby?: ?string,
owns?: ?string
},
accessibilityRole?: ?string,
accessibilityState?: {
busy?: ?boolean,
@@ -123,6 +114,7 @@ export type ViewProps = {
style?: GenericStyleProp<ViewStyle>,
testID?: ?string,
// unstable
dataSet?: ?Object,
onMouseDown?: (e: any) => void,
onMouseEnter?: (e: any) => void,
onMouseLeave?: (e: any) => void,
@@ -142,7 +134,5 @@ export type ViewProps = {
onWheel?: (e: any) => void,
href?: ?string,
rel?: ?string,
target?: ?string,
unstable_ariaSet?: Object,
unstable_dataSet?: Object
target?: ?string
};
@@ -19,7 +19,7 @@ describe('modules/AccessibilityUtil/propsToAccessibilityComponent', () => {
expect(
propsToAccessibilityComponent({
accessibilityRole: 'heading',
unstable_ariaSet: { level: 3 }
'aria-level': 3
})
).toEqual('h3');
});
@@ -34,9 +34,8 @@ const propsToAccessibilityComponent = (props: Object = emptyObject) => {
const role = propsToAriaRole(props);
if (role) {
if (role === 'heading') {
const ariaSet = props.unstable_ariaSet;
if (ariaSet != null && ariaSet.level) {
const level = ariaSet.level;
const level = props['aria-level'];
if (level != null) {
return `h${level}`;
}
return 'h1';
@@ -14,20 +14,6 @@ exports[`modules/createDOMProps includes cursor style for pressable roles 1`] =
exports[`modules/createDOMProps includes cursor style for pressable roles 2`] = `"css-cursor-18t94o4"`;
exports[`modules/createDOMProps prop "accessibilityRelationship" values are "id" string 1`] = `
Object {
"aria-activedescendant": "id",
"aria-controls": "id",
"aria-describedby": "id",
"aria-details": "id",
"aria-haspopup": "id",
"aria-labelledby": "id",
"aria-owns": "id",
}
`;
exports[`modules/createDOMProps prop "accessibilityRelationship" values are "undefined" 1`] = `Object {}`;
exports[`modules/createDOMProps prop "accessibilityState" values are "false" 1`] = `
Object {
"aria-busy": false,
@@ -195,32 +195,6 @@ describe('modules/createDOMProps', () => {
});
});
describe('prop "accessibilityRelationship"', () => {
function createAccessibilityRelationship(value) {
return {
activedescendant: value,
controls: value,
describedby: value,
details: value,
haspopup: value,
labelledby: value,
owns: value
};
}
test('values are "undefined"', () => {
const accessibilityRelationship = createAccessibilityRelationship(undefined);
const props = createProps({ accessibilityRelationship });
expect(props).toMatchSnapshot();
});
test('values are "id" string', () => {
const accessibilityRelationship = createAccessibilityRelationship('id');
const props = createProps({ accessibilityRelationship });
expect(props).toMatchSnapshot();
});
});
test('prop "className" is preserved', () => {
const className = 'external-class-name';
const props = createProps({ className });
@@ -50,13 +50,7 @@ const pointerEventsStyles = StyleSheet.create({
}
});
const defaultStyleResolver = (style, classList) => styleResolver.resolve(style, classList);
const createDOMProps = (component, props, styleResolver) => {
if (!styleResolver) {
styleResolver = defaultStyleResolver;
}
const createDOMProps = (component, props) => {
if (!props) {
props = emptyObject;
}
@@ -64,11 +58,11 @@ const createDOMProps = (component, props, styleResolver) => {
const {
accessibilityLabel,
accessibilityLiveRegion,
accessibilityRelationship,
accessibilityState,
accessibilityValue,
accessible,
classList,
dataSet,
disabled: providedDisabled,
importantForAccessibility,
nativeID,
@@ -78,8 +72,6 @@ const createDOMProps = (component, props, styleResolver) => {
/* eslint-disable */
accessibilityRole,
/* eslint-enable */
unstable_ariaSet,
unstable_dataSet,
...domProps
} = props;
@@ -95,23 +87,11 @@ const createDOMProps = (component, props, styleResolver) => {
component === 'textarea' ||
domProps.contentEditable != null;
// unstable_ariaSet
if (unstable_ariaSet != null) {
for (const prop in unstable_ariaSet) {
if (hasOwnProperty.call(unstable_ariaSet, prop)) {
const value = unstable_ariaSet[prop];
if (value != null) {
domProps[`aria-${prop}`] = value;
}
}
}
}
// unstable_dataSet
if (unstable_dataSet != null) {
for (const prop in unstable_dataSet) {
if (hasOwnProperty.call(unstable_dataSet, prop)) {
const value = unstable_dataSet[prop];
// dataSet
if (dataSet != null) {
for (const prop in dataSet) {
if (hasOwnProperty.call(dataSet, prop)) {
const value = dataSet[prop];
if (value != null) {
domProps[`data-${prop}`] = value;
}
@@ -129,16 +109,6 @@ const createDOMProps = (component, props, styleResolver) => {
domProps['aria-live'] = accessibilityLiveRegion === 'none' ? 'off' : accessibilityLiveRegion;
}
// accessibilityRelationship
if (accessibilityRelationship != null) {
for (const prop in accessibilityRelationship) {
const value = accessibilityRelationship[prop];
if (value != null) {
domProps[`aria-${prop}`] = value;
}
}
}
// accessibilityRole
if (role != null) {
domProps.role = role;
@@ -224,7 +194,7 @@ const createDOMProps = (component, props, styleResolver) => {
const finalClassList = [needsReset && classes.reset, needsCursor && classes.cursor, classList];
// Resolve styles
const { className, style } = styleResolver(reactNativeStyle, finalClassList);
const { className, style } = styleResolver.resolve(reactNativeStyle, finalClassList);
if (className != null && className !== '') {
domProps.className = className;
+5 -1
View File
@@ -11,7 +11,11 @@ export default function pick(obj: Object, list: { [string]: boolean }): Object {
const nextObj = {};
for (const key in obj) {
if (obj.hasOwnProperty(key)) {
if (list[key] === true) {
if (
list[key] === true ||
// Temporary until ARIA is mapped to explicit props
key.indexOf('aria-') === 0
) {
nextObj[key] = obj[key];
}
}