Skip to content

Commit 4c732b4

Browse files
fabriziocuccimeta-codesync[bot]
authored andcommitted
Add accessibilityRole=link if Text is pressable (#54490)
Summary: Pull Request resolved: #54490 Changelog: [General][Changed] - Text components with onPress or onLongPress now automatically get accessibilityRole='link' for proper accessibility support ## Background React Native on Android only generates ClickableSpans when the associated JS element uses `role="link"` or `accessibilityRole="link"`. Without ClickableSpans, accessibility tools cannot properly identify these interactive text elements. ### This Change This change makes React Native automatically set `accessibilityRole='link'` on Text components that are pressable, unless an explicit `accessibilityRole`/`role` is already provided. Reviewed By: javache Differential Revision: D86657563 fbshipit-source-id: cc1b6f1f91c22d5b6cf7fc4487eeeb612c4a752a
1 parent 17d184c commit 4c732b4

4 files changed

Lines changed: 356 additions & 7 deletions

File tree

packages/react-native/Libraries/Text/Text.js

Lines changed: 42 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ if (ReactNativeFeatureFlags.reduceDefaultPropsInText()) {
4545
ref: forwardedRef,
4646
accessible,
4747
accessibilityLabel,
48+
accessibilityRole,
4849
accessibilityState,
4950
allowFontScaling,
5051
'aria-busy': ariaBusy,
@@ -71,6 +72,7 @@ if (ReactNativeFeatureFlags.reduceDefaultPropsInText()) {
7172
onResponderTerminationRequest,
7273
onStartShouldSetResponder,
7374
pressRetentionOffset,
75+
role,
7476
selectable,
7577
selectionColor,
7678
suppressHighlighting,
@@ -149,6 +151,17 @@ if (ReactNativeFeatureFlags.reduceDefaultPropsInText()) {
149151
onStartShouldSetResponder != null) &&
150152
_disabled !== true;
151153

154+
const shouldUseLinkRole =
155+
ReactNativeFeatureFlags.shouldUseLinkRoleForPressableText() &&
156+
isPressable &&
157+
accessibilityRole == null &&
158+
role == null;
159+
160+
const _accessibilityRole =
161+
accessibilityRole ?? (shouldUseLinkRole ? 'link' : undefined);
162+
163+
const _role = shouldUseLinkRole ? undefined : role;
164+
152165
// TODO: Move this processing to the view configuration.
153166
const _selectionColor =
154167
selectionColor != null ? processColor(selectionColor) : undefined;
@@ -206,6 +219,9 @@ if (ReactNativeFeatureFlags.reduceDefaultPropsInText()) {
206219
if (_accessibilityLabel !== undefined) {
207220
processedProps.accessibilityLabel = _accessibilityLabel;
208221
}
222+
if (_accessibilityRole !== undefined) {
223+
processedProps.accessibilityRole = _accessibilityRole;
224+
}
209225
if (_accessibilityState !== undefined) {
210226
processedProps.accessibilityState = _accessibilityState;
211227
}
@@ -224,6 +240,9 @@ if (ReactNativeFeatureFlags.reduceDefaultPropsInText()) {
224240
if (_selectionColor !== undefined) {
225241
processedProps.selectionColor = _selectionColor;
226242
}
243+
if (_role !== undefined) {
244+
processedProps.role = _role;
245+
}
227246

228247
let textPressabilityProps: ?TextPressabilityProps;
229248
if (isPressable) {
@@ -317,6 +336,7 @@ if (ReactNativeFeatureFlags.reduceDefaultPropsInText()) {
317336
accessibilityElementsHidden,
318337
importantForAccessibility,
319338
accessibilityLabel,
339+
accessibilityRole,
320340
accessibilityState,
321341
allowFontScaling,
322342
'aria-busy': ariaBusy,
@@ -343,6 +363,7 @@ if (ReactNativeFeatureFlags.reduceDefaultPropsInText()) {
343363
onResponderTerminationRequest,
344364
onStartShouldSetResponder,
345365
pressRetentionOffset,
366+
role,
346367
selectable,
347368
selectionColor,
348369
suppressHighlighting,
@@ -398,6 +419,17 @@ if (ReactNativeFeatureFlags.reduceDefaultPropsInText()) {
398419
onStartShouldSetResponder != null) &&
399420
_disabled !== true;
400421

422+
const shouldUseLinkRole =
423+
ReactNativeFeatureFlags.shouldUseLinkRoleForPressableText() &&
424+
isPressable &&
425+
accessibilityRole == null &&
426+
role == null;
427+
428+
const _accessibilityRole =
429+
accessibilityRole ?? (shouldUseLinkRole ? 'link' : undefined);
430+
431+
const _role = shouldUseLinkRole ? undefined : role;
432+
401433
// TODO: Move this processing to the view configuration.
402434
const _selectionColor =
403435
selectionColor != null ? processColor(selectionColor) : undefined;
@@ -462,6 +494,7 @@ if (ReactNativeFeatureFlags.reduceDefaultPropsInText()) {
462494
...restProps,
463495
accessibilityElementsHidden: _accessibilityElementsHidden,
464496
accessibilityLabel: _accessibilityLabel,
497+
accessibilityRole: _accessibilityRole,
465498
accessibilityState: _accessibilityState,
466499
importantForAccessibility: _importantForAccessibility,
467500
nativeID: _nativeID,
@@ -470,6 +503,7 @@ if (ReactNativeFeatureFlags.reduceDefaultPropsInText()) {
470503
selectionColor: _selectionColor,
471504
style: _style,
472505
disabled: disabled,
506+
role: _role,
473507
children,
474508
}}
475509
textPressabilityProps={{
@@ -495,6 +529,7 @@ if (ReactNativeFeatureFlags.reduceDefaultPropsInText()) {
495529
{...restProps}
496530
accessibilityElementsHidden={_accessibilityElementsHidden}
497531
accessibilityLabel={_accessibilityLabel}
532+
accessibilityRole={_accessibilityRole}
498533
accessibilityState={_accessibilityState}
499534
importantForAccessibility={_importantForAccessibility}
500535
nativeID={_nativeID}
@@ -503,7 +538,8 @@ if (ReactNativeFeatureFlags.reduceDefaultPropsInText()) {
503538
selectable={_selectable}
504539
selectionColor={_selectionColor}
505540
style={_style}
506-
disabled={disabled}>
541+
disabled={disabled}
542+
role={_role}>
507543
{children}
508544
</NativeVirtualText>
509545
);
@@ -538,6 +574,7 @@ if (ReactNativeFeatureFlags.reduceDefaultPropsInText()) {
538574
...restProps,
539575
accessibilityElementsHidden: _accessibilityElementsHidden,
540576
accessibilityLabel: _accessibilityLabel,
577+
accessibilityRole: _accessibilityRole,
541578
accessibilityState: _accessibilityState,
542579
accessible: _accessible,
543580
allowFontScaling: allowFontScaling !== false,
@@ -549,6 +586,7 @@ if (ReactNativeFeatureFlags.reduceDefaultPropsInText()) {
549586
selectable: _selectable,
550587
selectionColor: _selectionColor,
551588
style: _style,
589+
role: _role,
552590
children,
553591
}}
554592
textPressabilityProps={{
@@ -573,6 +611,7 @@ if (ReactNativeFeatureFlags.reduceDefaultPropsInText()) {
573611
{...restProps}
574612
accessibilityElementsHidden={_accessibilityElementsHidden}
575613
accessibilityLabel={_accessibilityLabel}
614+
accessibilityRole={_accessibilityRole}
576615
accessibilityState={_accessibilityState}
577616
accessible={_accessible}
578617
allowFontScaling={allowFontScaling !== false}
@@ -584,7 +623,8 @@ if (ReactNativeFeatureFlags.reduceDefaultPropsInText()) {
584623
ref={forwardedRef}
585624
selectable={_selectable}
586625
selectionColor={_selectionColor}
587-
style={_style}>
626+
style={_style}
627+
role={_role}>
588628
{children}
589629
</NativeText>
590630
);

0 commit comments

Comments
 (0)