Skip to content

Commit

Permalink
[change] Support W3C ARIA props and styles
Browse files Browse the repository at this point in the history
* Add support for 'aria-*' and 'role' props.
* Add support for 'id' and 'tabIndex' props.
* Add support for 'pointerEvents' and 'userSelect' styles.
* Deprecate 'accessibility*' props.
* Deprecate 'nativeId' and 'focusable' props.
* Deprecate 'pointerEvents' and 'selectable' props.

Ref #2379
  • Loading branch information
necolas committed Mar 20, 2023
1 parent 2874b28 commit 67d52a4
Show file tree
Hide file tree
Showing 15 changed files with 913 additions and 245 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,55 +19,30 @@ exports[`components/Text nested 1`] = `
</div>
`;

exports[`components/Text prop "accessibilityLabel" value is set 1`] = `
exports[`components/Text prop "aria-label" value is set 1`] = `
<div
aria-label="accessibility label"
class="css-text-1rynq56"
dir="auto"
/>
`;

exports[`components/Text prop "accessibilityLabelledBy" value is set 1`] = `
exports[`components/Text prop "aria-labelledby" value is set 1`] = `
<div
aria-labelledby="123"
class="css-text-1rynq56"
dir="auto"
/>
`;

exports[`components/Text prop "accessibilityLiveRegion" value is set 1`] = `
exports[`components/Text prop "aria-live" value is set 1`] = `
<div
aria-live="polite"
class="css-text-1rynq56"
dir="auto"
/>
`;

exports[`components/Text prop "accessibilityRole" value alters HTML element 1`] = `
<article
class="css-text-1rynq56"
dir="auto"
role="article"
/>
`;

exports[`components/Text prop "accessibilityRole" value is "button" 1`] = `
<button
class="css-text-1rynq56"
dir="auto"
role="button"
type="button"
/>
`;

exports[`components/Text prop "accessibilityRole" value is set 1`] = `
<div
class="css-text-1rynq56"
dir="auto"
role="presentation"
/>
`;

exports[`components/Text prop "dir" value is "ltr" 1`] = `
<div
class="css-text-1rynq56"
Expand Down Expand Up @@ -187,6 +162,31 @@ exports[`components/Text prop "numberOfLines" value is set to one 1`] = `
/>
`;

exports[`components/Text prop "role" value alters HTML element 1`] = `
<article
class="css-text-1rynq56"
dir="auto"
role="article"
/>
`;

exports[`components/Text prop "role" value is "button" 1`] = `
<button
class="css-text-1rynq56"
dir="auto"
role="button"
type="button"
/>
`;

exports[`components/Text prop "role" value is set 1`] = `
<div
class="css-text-1rynq56"
dir="auto"
role="presentation"
/>
`;

exports[`components/Text prop "selectable" value of false 1`] = `
<div
class="css-text-1rynq56 r-userSelect-lrvibr"
Expand Down
22 changes: 10 additions & 12 deletions packages/react-native-web/src/exports/Text/__tests__/index-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,42 +23,40 @@ describe('components/Text', () => {
expect(container.firstChild).toMatchSnapshot();
});

describe('prop "accessibilityLabel"', () => {
describe('prop "aria-label"', () => {
test('value is set', () => {
const { container } = render(
<Text accessibilityLabel="accessibility label" />
);
const { container } = render(<Text aria-label="accessibility label" />);
expect(container.firstChild).toMatchSnapshot();
});
});

describe('prop "accessibilityLabelledBy"', () => {
describe('prop "aria-labelledby"', () => {
test('value is set', () => {
const { container } = render(<Text accessibilityLabelledBy="123" />);
const { container } = render(<Text aria-labelledby="123" />);
expect(container.firstChild).toMatchSnapshot();
});
});

describe('prop "accessibilityLiveRegion"', () => {
describe('prop "aria-live"', () => {
test('value is set', () => {
const { container } = render(<Text accessibilityLiveRegion="polite" />);
const { container } = render(<Text aria-live="polite" />);
expect(container.firstChild).toMatchSnapshot();
});
});

describe('prop "accessibilityRole"', () => {
describe('prop "role"', () => {
test('value is set', () => {
const { container } = render(<Text accessibilityRole="none" />);
const { container } = render(<Text role="none" />);
expect(container.firstChild).toMatchSnapshot();
});

test('value is "button"', () => {
const { container } = render(<Text accessibilityRole="button" />);
const { container } = render(<Text role="button" />);
expect(container.firstChild).toMatchSnapshot();
});

test('value alters HTML element', () => {
const { container } = render(<Text accessibilityRole="article" />);
const { container } = render(<Text role="article" />);
expect(container.firstChild).toMatchSnapshot();
});
});
Expand Down
8 changes: 8 additions & 0 deletions packages/react-native-web/src/exports/Text/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import useResponderEvents from '../../modules/useResponderEvents';
import StyleSheet from '../StyleSheet';
import TextAncestorContext from './TextAncestorContext';
import { useLocaleContext, getLocaleDirection } from '../../modules/useLocale';
import { warnOnce } from '../../modules/warnOnce';

const forwardPropsList = Object.assign(
{},
Expand Down Expand Up @@ -70,6 +71,13 @@ const Text: React.AbstractComponent<TextProps, HTMLElement & PlatformMethods> =
...rest
} = props;

if (selectable != null) {
warnOnce(
'selectable',
'selectable prop is deprecated. Use styles.userSelect.'
);
}

const hasTextAncestor = React.useContext(TextAncestorContext);
const hostRef = React.useRef(null);
const { direction: contextDirection } = useLocaleContext();
Expand Down
22 changes: 16 additions & 6 deletions packages/react-native-web/src/exports/Text/types.js
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ export type TextStyle = {
| 'isolate'
| 'isolate-override'
| 'plaintext',
userSelect?: 'none' | 'text',
whiteSpace?: ?string,
wordBreak?: 'normal' | 'break-all' | 'break-word' | 'keep-all',
wordWrap?: ?string,
Expand All @@ -89,6 +90,20 @@ export type TextStyle = {

export type TextProps = {
...ViewProps,
dir?: 'auto' | 'ltr' | 'rtl',
numberOfLines?: ?number,
role?:
| 'button'
| 'header'
| 'heading'
| 'label'
| 'link'
| 'listitem'
| 'none'
| 'text',
style?: GenericStyleProp<TextStyle>,
testID?: ?string,
// @deprecated
accessibilityRole?:
| 'button'
| 'header'
Expand All @@ -98,11 +113,6 @@ export type TextProps = {
| 'listitem'
| 'none'
| 'text',
dir?: 'auto' | 'ltr' | 'rtl',
lang?: string,
numberOfLines?: ?number,
onPress?: (e: any) => void,
selectable?: boolean,
style?: GenericStyleProp<TextStyle>,
testID?: ?string
selectable?: boolean
};
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,6 @@ export type Props = $ReadOnly<{|
accessibilityLabel?: $PropertyType<ViewProps, 'accessibilityLabel'>,
accessibilityLiveRegion?: $PropertyType<ViewProps, 'accessibilityLiveRegion'>,
accessibilityRole?: $PropertyType<ViewProps, 'accessibilityRole'>,
accessibilityState?: $PropertyType<ViewProps, 'accessibilityState'>,
accessibilityValue?: $PropertyType<ViewProps, 'accessibilityValue'>,
children?: ?React.Node,
delayLongPress?: ?number,
delayPressIn?: ?number,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,49 +17,27 @@ exports[`components/View non-text is rendered 1`] = `
</div>
`;

exports[`components/View prop "accessibilityLabel" value is set 1`] = `
exports[`components/View prop "aria-label" value is set 1`] = `
<div
aria-label="accessibility label"
class="css-view-175oi2r"
/>
`;

exports[`components/View prop "accessibilityLabelledBy" value is set 1`] = `
exports[`components/View prop "aria-labelledby" value is set 1`] = `
<div
aria-labelledby="123"
class="css-view-175oi2r"
/>
`;

exports[`components/View prop "accessibilityLiveRegion" value is set 1`] = `
exports[`components/View prop "aria-live" value is set 1`] = `
<div
aria-live="polite"
class="css-view-175oi2r"
/>
`;

exports[`components/View prop "accessibilityRole" value alters HTML element 1`] = `
<article
class="css-view-175oi2r"
role="article"
/>
`;

exports[`components/View prop "accessibilityRole" value is "button" 1`] = `
<button
class="css-view-175oi2r"
role="button"
type="button"
/>
`;

exports[`components/View prop "accessibilityRole" value is set 1`] = `
<div
class="css-view-175oi2r"
role="presentation"
/>
`;

exports[`components/View prop "dir" value is "ltr" 1`] = `
<div
class="css-view-175oi2r"
Expand Down Expand Up @@ -163,6 +141,28 @@ exports[`components/View prop "pointerEvents" 1`] = `
/>
`;

exports[`components/View prop "role" value alters HTML element 1`] = `
<article
class="css-view-175oi2r"
role="article"
/>
`;

exports[`components/View prop "role" value is "button" 1`] = `
<button
class="css-view-175oi2r"
role="button"
type="button"
/>
`;

exports[`components/View prop "role" value is set 1`] = `
<div
class="css-view-175oi2r"
role="presentation"
/>
`;

exports[`components/View prop "style" value is set 1`] = `
<div
class="css-view-175oi2r"
Expand Down
22 changes: 10 additions & 12 deletions packages/react-native-web/src/exports/View/__tests__/index-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,42 +49,40 @@ describe('components/View', () => {
});
});

describe('prop "accessibilityLabel"', () => {
describe('prop "aria-label"', () => {
test('value is set', () => {
const { container } = render(
<View accessibilityLabel="accessibility label" />
);
const { container } = render(<View aria-label="accessibility label" />);
expect(container.firstChild).toMatchSnapshot();
});
});

describe('prop "accessibilityLabelledBy"', () => {
describe('prop "aria-labelledby"', () => {
test('value is set', () => {
const { container } = render(<View accessibilityLabelledBy="123" />);
const { container } = render(<View aria-labelledby="123" />);
expect(container.firstChild).toMatchSnapshot();
});
});

describe('prop "accessibilityLiveRegion"', () => {
describe('prop "aria-live"', () => {
test('value is set', () => {
const { container } = render(<View accessibilityLiveRegion="polite" />);
const { container } = render(<View aria-live="polite" />);
expect(container.firstChild).toMatchSnapshot();
});
});

describe('prop "accessibilityRole"', () => {
describe('prop "role"', () => {
test('value is set', () => {
const { container } = render(<View accessibilityRole="none" />);
const { container } = render(<View role="none" />);
expect(container.firstChild).toMatchSnapshot();
});

test('value is "button"', () => {
const { container } = render(<View accessibilityRole="button" />);
const { container } = render(<View role="button" />);
expect(container.firstChild).toMatchSnapshot();
});

test('value alters HTML element', () => {
const { container } = render(<View accessibilityRole="article" />);
const { container } = render(<View role="article" />);
expect(container.firstChild).toMatchSnapshot();
});
});
Expand Down
3 changes: 0 additions & 3 deletions packages/react-native-web/src/exports/View/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,6 @@ const forwardPropsList = Object.assign(
forwardedProps.defaultProps,
forwardedProps.accessibilityProps,
forwardedProps.clickProps,
forwardedProps.defaultProps,
forwardedProps.accessibilityProps,
forwardedProps.clickProps,
forwardedProps.focusProps,
forwardedProps.keyboardProps,
forwardedProps.mouseProps,
Expand Down
Loading

0 comments on commit 67d52a4

Please sign in to comment.