Skip to content

Commit 720cdbc

Browse files
Viraj-10facebook-github-bot
authored andcommitted
feat: adding aria-label alias for accessibilityLabel (#34502)
Summary: - Adding [aria-label](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label) alias for [accessibilityLabel](https://reactnative.dev/docs/accessibility#accessibilitylabel) #34424 ## Changelog [General] [Added] - Add `aria-label` prop to `Button`, `View`, `Pressable` component Pull Request resolved: #34502 Test Plan: ``` <Button onPress={() => onButtonPress('cancelled')} testID="cancel_button" color={theme.SystemRedColor} title="Cancel Application" aria-lable="Press to cancel your application!" /> ``` Reviewed By: NickGerleman Differential Revision: D39055178 Pulled By: cipolleschi fbshipit-source-id: 7513a4518dedd0834e99fa8e72b07e0dc0132b41
1 parent 0f98041 commit 720cdbc

18 files changed

+117
-7
lines changed

Libraries/Components/Button.flow.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,11 @@ type ButtonProps = $ReadOnly<{|
119119
Text to display for blindness accessibility features.
120120
*/
121121
accessibilityLabel?: ?string,
122-
122+
/**
123+
* Alias for accessibilityLabel https://reactnative.dev/docs/view#accessibilitylabel
124+
* https://github.com/facebook/react-native/issues/34424
125+
*/
126+
'aria-label'?: ?string,
123127
/**
124128
If `true`, disable all interactions for this component.
125129

Libraries/Components/Button.js

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,11 @@ type ButtonProps = $ReadOnly<{|
126126
Text to display for blindness accessibility features.
127127
*/
128128
accessibilityLabel?: ?string,
129-
129+
/**
130+
* Alias for accessibilityLabel https://reactnative.dev/docs/view#accessibilitylabel
131+
* https://github.com/facebook/react-native/issues/34424
132+
*/
133+
'aria-label'?: ?string,
130134
/**
131135
If `true`, disable all interactions for this component.
132136
@@ -286,6 +290,7 @@ class Button extends React.Component<ButtonProps> {
286290
'aria-checked': ariaChecked,
287291
'aria-disabled': ariaDisabled,
288292
'aria-expanded': ariaExpanded,
293+
'aria-label': ariaLabel,
289294
'aria-selected': ariaSelected,
290295
importantForAccessibility,
291296
color,
@@ -358,7 +363,7 @@ class Button extends React.Component<ButtonProps> {
358363
accessible={accessible}
359364
accessibilityActions={accessibilityActions}
360365
onAccessibilityAction={onAccessibilityAction}
361-
accessibilityLabel={accessibilityLabel}
366+
accessibilityLabel={ariaLabel || accessibilityLabel}
362367
accessibilityHint={accessibilityHint}
363368
accessibilityLanguage={accessibilityLanguage}
364369
accessibilityRole="button"

Libraries/Components/Pressable/Pressable.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,11 @@ type Props = $ReadOnly<{|
185185
* Duration to wait after press down before calling `onPressIn`.
186186
*/
187187
unstable_pressDelay?: ?number,
188+
/**
189+
* Web to Native Accessibilty props
190+
* https://github.com/facebook/react-native/issues/34424
191+
*/
192+
'aria-label'?: ?string,
188193
|}>;
189194

190195
/**
@@ -204,6 +209,7 @@ function Pressable(props: Props, forwardedRef): React.Node {
204209
'aria-checked': ariaChecked,
205210
'aria-disabled': ariaDisabled,
206211
'aria-expanded': ariaExpanded,
212+
'aria-label': ariaLabel,
207213
'aria-selected': ariaSelected,
208214
cancelable,
209215
children,
@@ -254,11 +260,13 @@ function Pressable(props: Props, forwardedRef): React.Node {
254260
const accessibilityLiveRegion =
255261
ariaLive === 'off' ? 'none' : ariaLive ?? props.accessibilityLiveRegion;
256262

263+
const accessibilityLabel = ariaLabel ?? props.accessibilityLabel;
257264
const restPropsWithDefaults: React.ElementConfig<typeof View> = {
258265
...restProps,
259266
...android_rippleConfig?.viewProps,
260267
accessible: accessible !== false,
261268
accessibilityLiveRegion,
269+
accessibilityLabel,
262270
accessibilityState: _accessibilityState,
263271
focusable: focusable !== false,
264272
accessibilityValue,

Libraries/Components/Touchable/TouchableBounce.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -153,11 +153,13 @@ class TouchableBounce extends React.Component<Props, State> {
153153
text: this.props['aria-valuetext'] ?? this.props.accessibilityValue?.text,
154154
};
155155

156+
const accessibilityLabel =
157+
this.props['aria-label'] ?? this.props.accessibilityLabel;
156158
return (
157159
<Animated.View
158160
style={[{transform: [{scale: this.state.scale}]}, this.props.style]}
159161
accessible={this.props.accessible !== false}
160-
accessibilityLabel={this.props.accessibilityLabel}
162+
accessibilityLabel={accessibilityLabel}
161163
accessibilityHint={this.props.accessibilityHint}
162164
accessibilityLanguage={this.props.accessibilityLanguage}
163165
accessibilityRole={this.props.accessibilityRole}

Libraries/Components/Touchable/TouchableHighlight.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -303,10 +303,12 @@ class TouchableHighlight extends React.Component<Props, State> {
303303
? 'none'
304304
: this.props['aria-live'] ?? this.props.accessibilityLiveRegion;
305305

306+
const accessibilityLabel =
307+
this.props['aria-label'] ?? this.props.accessibilityLabel;
306308
return (
307309
<View
308310
accessible={this.props.accessible !== false}
309-
accessibilityLabel={this.props.accessibilityLabel}
311+
accessibilityLabel={accessibilityLabel}
310312
accessibilityHint={this.props.accessibilityHint}
311313
accessibilityLanguage={this.props.accessibilityLanguage}
312314
accessibilityRole={this.props.accessibilityRole}

Libraries/Components/Touchable/TouchableNativeFeedback.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -285,6 +285,8 @@ class TouchableNativeFeedback extends React.Component<Props, State> {
285285
? 'none'
286286
: this.props['aria-live'] ?? this.props.accessibilityLiveRegion;
287287

288+
const accessibilityLabel =
289+
this.props['aria-label'] ?? this.props.accessibilityLabel;
288290
return React.cloneElement(
289291
element,
290292
{
@@ -298,7 +300,7 @@ class TouchableNativeFeedback extends React.Component<Props, State> {
298300
accessible: this.props.accessible !== false,
299301
accessibilityHint: this.props.accessibilityHint,
300302
accessibilityLanguage: this.props.accessibilityLanguage,
301-
accessibilityLabel: this.props.accessibilityLabel,
303+
accessibilityLabel: accessibilityLabel,
302304
accessibilityRole: this.props.accessibilityRole,
303305
accessibilityState: _accessibilityState,
304306
accessibilityActions: this.props.accessibilityActions,

Libraries/Components/Touchable/TouchableOpacity.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -247,10 +247,12 @@ class TouchableOpacity extends React.Component<Props, State> {
247247
? 'none'
248248
: this.props['aria-live'] ?? this.props.accessibilityLiveRegion;
249249

250+
const accessibilityLabel =
251+
this.props['aria-label'] ?? this.props.accessibilityLabel;
250252
return (
251253
<Animated.View
252254
accessible={this.props.accessible !== false}
253-
accessibilityLabel={this.props.accessibilityLabel}
255+
accessibilityLabel={accessibilityLabel}
254256
accessibilityHint={this.props.accessibilityHint}
255257
accessibilityLanguage={this.props.accessibilityLanguage}
256258
accessibilityRole={this.props.accessibilityRole}

Libraries/Components/Touchable/TouchableWithoutFeedback.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ type Props = $ReadOnly<{|
5858
'aria-selected'?: ?boolean,
5959
'aria-hidden'?: ?boolean,
6060
'aria-live'?: ?('polite' | 'assertive' | 'off'),
61+
'aria-label'?: ?Stringish,
6162
children?: ?React.Node,
6263
delayLongPress?: ?number,
6364
delayPressIn?: ?number,

Libraries/Components/View/View.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,9 @@ const View: React.AbstractComponent<
3333
accessibilityElementsHidden,
3434
accessibilityLiveRegion,
3535
'aria-live': ariaLive,
36+
accessibilityLabel,
3637
accessibilityRole,
38+
'aria-label': ariaLabel,
3739
'aria-hidden': ariaHidden,
3840
focusable,
3941
importantForAccessibility,
@@ -148,6 +150,7 @@ const View: React.AbstractComponent<
148150
accessibilityLiveRegion={
149151
ariaLive === 'off' ? 'none' : ariaLive ?? accessibilityLiveRegion
150152
}
153+
accessibilityLabel={ariaLabel ?? accessibilityLabel}
151154
focusable={tabIndex !== undefined ? !tabIndex : focusable}
152155
accessibilityState={_accessibilityState}
153156
accessibilityRole={

Libraries/Components/View/ViewPropTypes.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -463,6 +463,12 @@ export type ViewProps = $ReadOnly<{|
463463
*/
464464
accessibilityHint?: ?Stringish,
465465

466+
/**
467+
* Alias for accessibilityLabel https://reactnative.dev/docs/view#accessibilitylabel
468+
* https://github.com/facebook/react-native/issues/34424
469+
*/
470+
'aria-label'?: ?Stringish,
471+
466472
/**
467473
* Indicates to the accessibility services that the UI component is in
468474
* a specific language. The provided string should be formatted following

Libraries/Image/Image.android.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,7 @@ const BaseImage = (props: ImagePropsType, forwardedRef) => {
180180
? loadingIndicatorSource.uri
181181
: null,
182182
ref: forwardedRef,
183+
accessibilityLabel: props['aria-label'] ?? props.accessibilityLabel,
183184
accessibilityState: {
184185
busy: props['aria-busy'] ?? props.accessibilityState?.busy,
185186
checked: props['aria-checked'] ?? props.accessibilityState?.checked,

Libraries/Image/Image.ios.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,7 @@ const BaseImage = (props: ImagePropsType, forwardedRef) => {
164164
expanded: ariaExpanded ?? props.accessibilityState?.expanded,
165165
selected: ariaSelected ?? props.accessibilityState?.selected,
166166
};
167+
const accessibilityLabel = props['aria-label'] ?? props.accessibilityLabel;
167168

168169
return (
169170
<ImageAnalyticsTagContext.Consumer>
@@ -172,6 +173,7 @@ const BaseImage = (props: ImagePropsType, forwardedRef) => {
172173
<ImageViewNativeComponent
173174
accessibilityState={_accessibilityState}
174175
{...restProps}
176+
accessibilityLabel={accessibilityLabel}
175177
ref={forwardedRef}
176178
style={style}
177179
resizeMode={resizeMode}

Libraries/Image/ImageProps.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,12 @@ export type ImageProps = {|
8787
*/
8888
accessibilityLabel?: ?Stringish,
8989

90+
/**
91+
* Alias for accessibilityLabel
92+
* See https://reactnative.dev/docs/image#accessibilitylabel
93+
*/
94+
'aria-label'?: ?Stringish,
95+
9096
/**
9197
* blurRadius: the blur radius of the blur filter added to the image
9298
*

Libraries/Text/Text.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,13 @@ const Text: React.AbstractComponent<
3333
> = React.forwardRef((props: TextProps, forwardedRef) => {
3434
const {
3535
accessible,
36+
accessibilityLabel,
3637
allowFontScaling,
3738
'aria-busy': ariaBusy,
3839
'aria-checked': ariaChecked,
3940
'aria-disabled': ariaDisabled,
4041
'aria-expanded': ariaExpanded,
42+
'aria-label': ariaLabel,
4143
'aria-selected': ariaSelected,
4244
ellipsizeMode,
4345
onLongPress,
@@ -202,6 +204,7 @@ const Text: React.AbstractComponent<
202204
{...restProps}
203205
accessibilityState={_accessibilityState}
204206
{...eventHandlersForText}
207+
accessibilityLabel={ariaLabel ?? accessibilityLabel}
205208
isHighlighted={isHighlighted}
206209
isPressable={isPressable}
207210
selectable={_selectable}
@@ -218,6 +221,7 @@ const Text: React.AbstractComponent<
218221
disabled={_disabled}
219222
selectable={_selectable}
220223
accessible={_accessible}
224+
accessibilityLabel={ariaLabel ?? accessibilityLabel}
221225
accessibilityState={nativeTextAccessibilityState}
222226
allowFontScaling={allowFontScaling !== false}
223227
ellipsizeMode={ellipsizeMode ?? 'tail'}

Libraries/Text/TextProps.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ export type TextProps = $ReadOnly<{|
5757
accessibilityLabel?: ?Stringish,
5858
accessibilityRole?: ?AccessibilityRole,
5959
accessibilityState?: ?AccessibilityState,
60+
'aria-label'?: ?string,
6061

6162
/**
6263
* Whether font should be scaled down automatically.

packages/rn-tester/js/examples/Button/ButtonExample.js

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,28 @@ exports.examples = [
176176
);
177177
},
178178
},
179+
{
180+
title: 'Button with aria-label="label"',
181+
description: ('Note: This prop changes the text that a screen ' +
182+
'reader announces (there are no visual differences).': string),
183+
render: function (): React.Node {
184+
return (
185+
<RNTesterThemeContext.Consumer>
186+
{theme => {
187+
return (
188+
<Button
189+
onPress={() => onButtonPress('submitted')}
190+
testID="aria_label_button"
191+
color={theme.LinkColor}
192+
title="Submit Application"
193+
aria-label="Press to submit your application!"
194+
/>
195+
);
196+
}}
197+
</RNTesterThemeContext.Consumer>
198+
);
199+
},
200+
},
179201
{
180202
title: 'Button with accessibilityState={{disabled: true}}',
181203
description:

packages/rn-tester/js/examples/Pressable/PressableExample.js

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,16 @@ import {
1717
Text,
1818
Platform,
1919
View,
20+
Alert,
2021
} from 'react-native';
2122
import ReactNativeFeatureFlags from 'react-native/Libraries/ReactNative/ReactNativeFeatureFlags';
2223

2324
const {useEffect, useRef, useState} = React;
2425

26+
function onPressablePress(pressableName: string) {
27+
Alert.alert(`Your application has been ${pressableName}!`);
28+
}
29+
2530
const forceTouchAvailable =
2631
(Platform.OS === 'ios' && Platform.constants.forceTouchAvailable) || false;
2732

@@ -81,6 +86,20 @@ function TextOnPressBox() {
8186
);
8287
}
8388

89+
function PressableAriaLabel() {
90+
return (
91+
<View style={[styles.row, styles.centered]}>
92+
<Pressable
93+
style={styles.wrapper}
94+
testID="pressable_aria_label"
95+
aria-label="pressable with aria label"
96+
accessibilityRole="button"
97+
onPress={() => onPressablePress('pressed')}>
98+
<Text style={styles.button}>Press Me</Text>
99+
</Pressable>
100+
</View>
101+
);
102+
}
84103
function PressableFeedbackEvents() {
85104
const [eventLog, setEventLog] = useState([]);
86105

@@ -524,6 +543,14 @@ const examples = [
524543
return <PressableDisabled />;
525544
},
526545
},
546+
{
547+
title: 'Pressable with aria-label="label"',
548+
description: ('Note: This prop changes the text that a screen ' +
549+
'reader announces (there are no visual differences).': string),
550+
render: function (): React.Node {
551+
return <PressableAriaLabel />;
552+
},
553+
},
527554
];
528555

529556
if (ReactNativeFeatureFlags.shouldPressibilityUseW3CPointerEventsForHover()) {

packages/rn-tester/js/examples/View/ViewExample.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -600,4 +600,16 @@ exports.examples = [
600600
);
601601
},
602602
},
603+
{
604+
title: 'View with aria-label="label"',
605+
render(): React.Node {
606+
return (
607+
<View
608+
aria-label="Blue background View with Text"
609+
style={{backgroundColor: '#527FE4', padding: 5}}>
610+
<Text style={{fontSize: 11}}>Blue background</Text>
611+
</View>
612+
);
613+
},
614+
},
603615
];

0 commit comments

Comments
 (0)