diff --git a/packages/docs/src/pages/docs/concepts/accessibility.md b/packages/docs/src/pages/docs/concepts/accessibility.md index d055a677..4be2c8f8 100644 --- a/packages/docs/src/pages/docs/concepts/accessibility.md +++ b/packages/docs/src/pages/docs/concepts/accessibility.md @@ -53,7 +53,7 @@ Equivalent to [aria-colindex](https://www.w3.org/TR/wai-aria-1.2/#aria-colindex) Equivalent to [aria-colspan](https://www.w3.org/TR/wai-aria-1.2/#aria-colspan). {% endcall %} -{% call macro.prop('accessibilityControls', '?string') %} +{% call macro.prop('accessibilityControls', '?(string | Array)') %} Equivalent to [aria-controls](https://www.w3.org/TR/wai-aria-1.2/#aria-controls). {% endcall %} @@ -61,7 +61,7 @@ Equivalent to [aria-controls](https://www.w3.org/TR/wai-aria-1.2/#aria-controls) Equivalent to [aria-current](https://www.w3.org/TR/wai-aria-1.2/#aria-current). {% endcall %} -{% call macro.prop('accessibilityDescribedBy', '?string') %} +{% call macro.prop('accessibilityDescribedBy', '?(string | Array)') %} Equivalent to [aria-describedby](https://www.w3.org/TR/wai-aria-1.2/#aria-describedby). {% endcall %} @@ -81,7 +81,7 @@ Equivalent to [aria-errormessage](https://www.w3.org/TR/wai-aria-1.2/#aria-error Equivalent to [aria-expanded](https://www.w3.org/TR/wai-aria-1.2/#aria-expanded). {% endcall %} -{% call macro.prop('accessibilityFlowTo', '?string') %} +{% call macro.prop('accessibilityFlowTo', '?(string | Array)') %} Equivalent to [aria-flowto](https://www.w3.org/TR/wai-aria-1.2/#aria-flowto). {% endcall %} @@ -105,7 +105,7 @@ Equivalent to [aria-keyshortcuts](https://www.w3.org/TR/wai-aria-1.2/#aria-keysh Equivalent to [aria-label](https://www.w3.org/TR/wai-aria-1.2/#aria-label). {% endcall %} -{% call macro.prop('accessibilityLabelledBy', '?string') %} +{% call macro.prop('accessibilityLabelledBy', '?(string | Array)') %} Equivalent to [aria-labelledby](https://www.w3.org/TR/wai-aria-1.2/#aria-labelledby). {% endcall %} @@ -133,7 +133,7 @@ Equivalent to [aria-multiselectable](https://www.w3.org/TR/wai-aria-1.2/#aria-mu Equivalent to [aria-orientation](https://www.w3.org/TR/wai-aria-1.2/#aria-orientation). {% endcall %} -{% call macro.prop('accessibilityOwns', '?string') %} +{% call macro.prop('accessibilityOwns', '?(string | Array)') %} Equivalent to [aria-owns](https://www.w3.org/TR/wai-aria-1.2/#aria-owns). {% endcall %} diff --git a/packages/react-native-web/src/exports/View/types.js b/packages/react-native-web/src/exports/View/types.js index adbc20bf..8cdabd9a 100644 --- a/packages/react-native-web/src/exports/View/types.js +++ b/packages/react-native-web/src/exports/View/types.js @@ -35,7 +35,7 @@ export type AccessibilityProps = {| accessibilityColumnSpan?: ?number, accessibilityControls?: ?idRefList, accessibilityCurrent?: ?(boolean | 'page' | 'step' | 'location' | 'date' | 'time'), - accessibilityDescribedBy?: ?idRef, + accessibilityDescribedBy?: ?idRefList, accessibilityDetails?: ?idRef, accessibilityDisabled?: ?boolean, accessibilityErrorMessage?: ?idRef, diff --git a/packages/react-native-web/src/exports/createElement/__tests__/index-test.js b/packages/react-native-web/src/exports/createElement/__tests__/index-test.js index f3f031ae..6ff5d737 100644 --- a/packages/react-native-web/src/exports/createElement/__tests__/index-test.js +++ b/packages/react-native-web/src/exports/createElement/__tests__/index-test.js @@ -111,6 +111,10 @@ describe('exports/createElement', () => { createElement('div', { accessibilityControls: 'abc' }) ); expect(getAttribute(hasValue, 'aria-controls')).toBe('abc'); + const { container: hasMultipleValues } = render( + createElement('div', { accessibilityControls: ['abc', 'def'] }) + ); + expect(getAttribute(hasMultipleValues, 'aria-controls')).toBe('abc def'); }); test('accessibilityCurrent', () => { @@ -131,6 +135,10 @@ describe('exports/createElement', () => { createElement('div', { accessibilityDescribedBy: 'abc' }) ); expect(getAttribute(hasValue, 'aria-describedby')).toBe('abc'); + const { container: hasMultipleValues } = render( + createElement('div', { accessibilityDescribedBy: ['abc', 'def'] }) + ); + expect(getAttribute(hasMultipleValues, 'aria-describedby')).toBe('abc def'); }); test('accessibilityDetails', () => { @@ -176,6 +184,10 @@ describe('exports/createElement', () => { expect(getAttribute(isEmpty, 'aria-flowto')).toBeNull(); const { container: hasValue } = render(createElement('div', { accessibilityFlowTo: 'abc' })); expect(getAttribute(hasValue, 'aria-flowto')).toBe('abc'); + const { container: hasMultipleValues } = render( + createElement('div', { accessibilityFlowTo: ['abc', 'def'] }) + ); + expect(getAttribute(hasMultipleValues, 'aria-flowto')).toBe('abc def'); }); test('accessibilityHasPopup', () => { @@ -230,6 +242,10 @@ describe('exports/createElement', () => { createElement('div', { accessibilityLabelledBy: 'abc' }) ); expect(getAttribute(hasValue, 'aria-labelledby')).toBe('abc'); + const { container: hasMultipleValues } = render( + createElement('div', { accessibilityLabelledBy: ['abc', 'def'] }) + ); + expect(getAttribute(hasMultipleValues, 'aria-labelledby')).toBe('abc def'); }); test('accessibilityLevel', () => { @@ -293,6 +309,10 @@ describe('exports/createElement', () => { expect(getAttribute(isEmpty, 'aria-owns')).toBeNull(); const { container: hasValue } = render(createElement('div', { accessibilityOwns: 'abc' })); expect(getAttribute(hasValue, 'aria-owns')).toBe('abc'); + const { container: hasMultipleValues } = render( + createElement('div', { accessibilityOwns: ['abc', 'def'] }) + ); + expect(getAttribute(hasMultipleValues, 'aria-owns')).toBe('abc def'); }); test('accessibilityPlaceholder', () => { diff --git a/packages/react-native-web/src/modules/createDOMProps/index.js b/packages/react-native-web/src/modules/createDOMProps/index.js index ae53dfd8..ffc51262 100644 --- a/packages/react-native-web/src/modules/createDOMProps/index.js +++ b/packages/react-native-web/src/modules/createDOMProps/index.js @@ -15,6 +15,7 @@ import { STYLE_GROUPS } from '../../exports/StyleSheet/constants'; const emptyObject = {}; const hasOwnProperty = Object.prototype.hasOwnProperty; +const isArray = Array.isArray; const uppercasePattern = /[A-Z]/g; function toHyphenLower(match) { @@ -23,6 +24,9 @@ function toHyphenLower(match) { function hyphenateString(str: string): string { return str.replace(uppercasePattern, toHyphenLower); } +function processIDRefList(idRefList: string | Array): string { + return isArray(idRefList) ? idRefList.join(' ') : idRefList; +} // Reset styles for heading, link, and list DOM elements const classes = css.create( @@ -193,13 +197,13 @@ const createDOMProps = (elementType, props) => { domProps['aria-colspan'] = accessibilityColumnSpan; } if (accessibilityControls != null) { - domProps['aria-controls'] = accessibilityControls; + domProps['aria-controls'] = processIDRefList(accessibilityControls); } if (accessibilityCurrent != null) { domProps['aria-current'] = accessibilityCurrent; } if (accessibilityDescribedBy != null) { - domProps['aria-describedby'] = accessibilityDescribedBy; + domProps['aria-describedby'] = processIDRefList(accessibilityDescribedBy); } if (accessibilityDetails != null) { domProps['aria-details'] = accessibilityDetails; @@ -224,7 +228,7 @@ const createDOMProps = (elementType, props) => { domProps['aria-expanded'] = accessibilityExpanded; } if (accessibilityFlowTo != null) { - domProps['aria-flowto'] = accessibilityFlowTo; + domProps['aria-flowto'] = processIDRefList(accessibilityFlowTo); } if (accessibilityHasPopup != null) { domProps['aria-haspopup'] = accessibilityHasPopup; @@ -242,7 +246,7 @@ const createDOMProps = (elementType, props) => { domProps['aria-label'] = accessibilityLabel; } if (accessibilityLabelledBy != null) { - domProps['aria-labelledby'] = accessibilityLabelledBy; + domProps['aria-labelledby'] = processIDRefList(accessibilityLabelledBy); } if (accessibilityLevel != null) { domProps['aria-level'] = accessibilityLevel; @@ -263,7 +267,7 @@ const createDOMProps = (elementType, props) => { domProps['aria-orientation'] = accessibilityOrientation; } if (accessibilityOwns != null) { - domProps['aria-owns'] = accessibilityOwns; + domProps['aria-owns'] = processIDRefList(accessibilityOwns); } if (accessibilityPlaceholder != null) { domProps['aria-placeholder'] = accessibilityPlaceholder;