Skip to content

Commit db9df2b

Browse files
Andrew Haywardnecolas
authored andcommitted
[fix] Accessibility ref lists
Generate string-separated values for accessibility props that accept an array of id strings. Close #2021
1 parent c9eb794 commit db9df2b

File tree

4 files changed

+35
-11
lines changed

4 files changed

+35
-11
lines changed

packages/docs/src/pages/docs/concepts/accessibility.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -53,15 +53,15 @@ Equivalent to [aria-colindex](https://www.w3.org/TR/wai-aria-1.2/#aria-colindex)
5353
Equivalent to [aria-colspan](https://www.w3.org/TR/wai-aria-1.2/#aria-colspan).
5454
{% endcall %}
5555

56-
{% call macro.prop('accessibilityControls', '?string') %}
56+
{% call macro.prop('accessibilityControls', '?(string | Array<string>)') %}
5757
Equivalent to [aria-controls](https://www.w3.org/TR/wai-aria-1.2/#aria-controls).
5858
{% endcall %}
5959

6060
{% call macro.prop('accessibilityCurrent', '?(boolean | "page" | "step" | "location" | "date" | "time")') %}
6161
Equivalent to [aria-current](https://www.w3.org/TR/wai-aria-1.2/#aria-current).
6262
{% endcall %}
6363

64-
{% call macro.prop('accessibilityDescribedBy', '?string') %}
64+
{% call macro.prop('accessibilityDescribedBy', '?(string | Array<string>)') %}
6565
Equivalent to [aria-describedby](https://www.w3.org/TR/wai-aria-1.2/#aria-describedby).
6666
{% endcall %}
6767

@@ -81,7 +81,7 @@ Equivalent to [aria-errormessage](https://www.w3.org/TR/wai-aria-1.2/#aria-error
8181
Equivalent to [aria-expanded](https://www.w3.org/TR/wai-aria-1.2/#aria-expanded).
8282
{% endcall %}
8383

84-
{% call macro.prop('accessibilityFlowTo', '?string') %}
84+
{% call macro.prop('accessibilityFlowTo', '?(string | Array<string>)') %}
8585
Equivalent to [aria-flowto](https://www.w3.org/TR/wai-aria-1.2/#aria-flowto).
8686
{% endcall %}
8787

@@ -105,7 +105,7 @@ Equivalent to [aria-keyshortcuts](https://www.w3.org/TR/wai-aria-1.2/#aria-keysh
105105
Equivalent to [aria-label](https://www.w3.org/TR/wai-aria-1.2/#aria-label).
106106
{% endcall %}
107107

108-
{% call macro.prop('accessibilityLabelledBy', '?string') %}
108+
{% call macro.prop('accessibilityLabelledBy', '?(string | Array<string>)') %}
109109
Equivalent to [aria-labelledby](https://www.w3.org/TR/wai-aria-1.2/#aria-labelledby).
110110
{% endcall %}
111111

@@ -133,7 +133,7 @@ Equivalent to [aria-multiselectable](https://www.w3.org/TR/wai-aria-1.2/#aria-mu
133133
Equivalent to [aria-orientation](https://www.w3.org/TR/wai-aria-1.2/#aria-orientation).
134134
{% endcall %}
135135

136-
{% call macro.prop('accessibilityOwns', '?string') %}
136+
{% call macro.prop('accessibilityOwns', '?(string | Array<string>)') %}
137137
Equivalent to [aria-owns](https://www.w3.org/TR/wai-aria-1.2/#aria-owns).
138138
{% endcall %}
139139

packages/react-native-web/src/exports/View/types.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ export type AccessibilityProps = {|
3535
accessibilityColumnSpan?: ?number,
3636
accessibilityControls?: ?idRefList,
3737
accessibilityCurrent?: ?(boolean | 'page' | 'step' | 'location' | 'date' | 'time'),
38-
accessibilityDescribedBy?: ?idRef,
38+
accessibilityDescribedBy?: ?idRefList,
3939
accessibilityDetails?: ?idRef,
4040
accessibilityDisabled?: ?boolean,
4141
accessibilityErrorMessage?: ?idRef,

packages/react-native-web/src/exports/createElement/__tests__/index-test.js

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,10 @@ describe('exports/createElement', () => {
111111
createElement('div', { accessibilityControls: 'abc' })
112112
);
113113
expect(getAttribute(hasValue, 'aria-controls')).toBe('abc');
114+
const { container: hasMultipleValues } = render(
115+
createElement('div', { accessibilityControls: ['abc', 'def'] })
116+
);
117+
expect(getAttribute(hasMultipleValues, 'aria-controls')).toBe('abc def');
114118
});
115119

116120
test('accessibilityCurrent', () => {
@@ -131,6 +135,10 @@ describe('exports/createElement', () => {
131135
createElement('div', { accessibilityDescribedBy: 'abc' })
132136
);
133137
expect(getAttribute(hasValue, 'aria-describedby')).toBe('abc');
138+
const { container: hasMultipleValues } = render(
139+
createElement('div', { accessibilityDescribedBy: ['abc', 'def'] })
140+
);
141+
expect(getAttribute(hasMultipleValues, 'aria-describedby')).toBe('abc def');
134142
});
135143

136144
test('accessibilityDetails', () => {
@@ -176,6 +184,10 @@ describe('exports/createElement', () => {
176184
expect(getAttribute(isEmpty, 'aria-flowto')).toBeNull();
177185
const { container: hasValue } = render(createElement('div', { accessibilityFlowTo: 'abc' }));
178186
expect(getAttribute(hasValue, 'aria-flowto')).toBe('abc');
187+
const { container: hasMultipleValues } = render(
188+
createElement('div', { accessibilityFlowTo: ['abc', 'def'] })
189+
);
190+
expect(getAttribute(hasMultipleValues, 'aria-flowto')).toBe('abc def');
179191
});
180192

181193
test('accessibilityHasPopup', () => {
@@ -230,6 +242,10 @@ describe('exports/createElement', () => {
230242
createElement('div', { accessibilityLabelledBy: 'abc' })
231243
);
232244
expect(getAttribute(hasValue, 'aria-labelledby')).toBe('abc');
245+
const { container: hasMultipleValues } = render(
246+
createElement('div', { accessibilityLabelledBy: ['abc', 'def'] })
247+
);
248+
expect(getAttribute(hasMultipleValues, 'aria-labelledby')).toBe('abc def');
233249
});
234250

235251
test('accessibilityLevel', () => {
@@ -293,6 +309,10 @@ describe('exports/createElement', () => {
293309
expect(getAttribute(isEmpty, 'aria-owns')).toBeNull();
294310
const { container: hasValue } = render(createElement('div', { accessibilityOwns: 'abc' }));
295311
expect(getAttribute(hasValue, 'aria-owns')).toBe('abc');
312+
const { container: hasMultipleValues } = render(
313+
createElement('div', { accessibilityOwns: ['abc', 'def'] })
314+
);
315+
expect(getAttribute(hasMultipleValues, 'aria-owns')).toBe('abc def');
296316
});
297317

298318
test('accessibilityPlaceholder', () => {

packages/react-native-web/src/modules/createDOMProps/index.js

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import { STYLE_GROUPS } from '../../exports/StyleSheet/constants';
1515

1616
const emptyObject = {};
1717
const hasOwnProperty = Object.prototype.hasOwnProperty;
18+
const isArray = Array.isArray;
1819

1920
const uppercasePattern = /[A-Z]/g;
2021
function toHyphenLower(match) {
@@ -23,6 +24,9 @@ function toHyphenLower(match) {
2324
function hyphenateString(str: string): string {
2425
return str.replace(uppercasePattern, toHyphenLower);
2526
}
27+
function processIDRefList(idRefList: string | Array<string>): string {
28+
return isArray(idRefList) ? idRefList.join(' ') : idRefList;
29+
}
2630

2731
// Reset styles for heading, link, and list DOM elements
2832
const classes = css.create(
@@ -193,13 +197,13 @@ const createDOMProps = (elementType, props) => {
193197
domProps['aria-colspan'] = accessibilityColumnSpan;
194198
}
195199
if (accessibilityControls != null) {
196-
domProps['aria-controls'] = accessibilityControls;
200+
domProps['aria-controls'] = processIDRefList(accessibilityControls);
197201
}
198202
if (accessibilityCurrent != null) {
199203
domProps['aria-current'] = accessibilityCurrent;
200204
}
201205
if (accessibilityDescribedBy != null) {
202-
domProps['aria-describedby'] = accessibilityDescribedBy;
206+
domProps['aria-describedby'] = processIDRefList(accessibilityDescribedBy);
203207
}
204208
if (accessibilityDetails != null) {
205209
domProps['aria-details'] = accessibilityDetails;
@@ -224,7 +228,7 @@ const createDOMProps = (elementType, props) => {
224228
domProps['aria-expanded'] = accessibilityExpanded;
225229
}
226230
if (accessibilityFlowTo != null) {
227-
domProps['aria-flowto'] = accessibilityFlowTo;
231+
domProps['aria-flowto'] = processIDRefList(accessibilityFlowTo);
228232
}
229233
if (accessibilityHasPopup != null) {
230234
domProps['aria-haspopup'] = accessibilityHasPopup;
@@ -242,7 +246,7 @@ const createDOMProps = (elementType, props) => {
242246
domProps['aria-label'] = accessibilityLabel;
243247
}
244248
if (accessibilityLabelledBy != null) {
245-
domProps['aria-labelledby'] = accessibilityLabelledBy;
249+
domProps['aria-labelledby'] = processIDRefList(accessibilityLabelledBy);
246250
}
247251
if (accessibilityLevel != null) {
248252
domProps['aria-level'] = accessibilityLevel;
@@ -263,7 +267,7 @@ const createDOMProps = (elementType, props) => {
263267
domProps['aria-orientation'] = accessibilityOrientation;
264268
}
265269
if (accessibilityOwns != null) {
266-
domProps['aria-owns'] = accessibilityOwns;
270+
domProps['aria-owns'] = processIDRefList(accessibilityOwns);
267271
}
268272
if (accessibilityPlaceholder != null) {
269273
domProps['aria-placeholder'] = accessibilityPlaceholder;

0 commit comments

Comments
 (0)