Skip to content

Commit 4471715

Browse files
Dennis Urtubiafacebook-github-bot
Dennis Urtubia
authored andcommitted
Adds accessiblity actions on core components (#31532)
Summary: Android: Adding custom actions (#30854). Adds accessiblity actions on core components (Button, TextInput, Text, and Picker). ## Changelog [General] [Added] - Adds accessiblity actions on core components Pull Request resolved: #31532 Test Plan: - `npm test` - Rendering of components on `RNTesterApp` using talkback: - Check if accessibility actions were available; ![image](https://user-images.githubusercontent.com/33161939/118381843-a668c180-b5c5-11eb-9ce4-016a49157dc5.png) - Trigger `activate` action for all components; ![image](https://user-images.githubusercontent.com/33161939/118381736-7bca3900-b5c4-11eb-82fb-32e824e1b38c.png) ## Notes - For `TextInput` an unexpected error is raised: ![image](https://user-images.githubusercontent.com/33161939/118381603-d1054b00-b5c2-11eb-93f2-1d5730ee2d24.png) Reviewed By: kacieb Differential Revision: D28654294 Pulled By: lunaleaps fbshipit-source-id: 80dd3f3c7aa27bbaf16ef12997e8f55952a02eb2
1 parent 52b51f0 commit 4471715

File tree

5 files changed

+121
-2
lines changed

5 files changed

+121
-2
lines changed

Libraries/Components/Button.js

+14-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,11 @@ import TouchableOpacity from './Touchable/TouchableOpacity';
2020
import View from './View/View';
2121
import invariant from 'invariant';
2222

23-
import type {AccessibilityState} from './View/ViewAccessibility';
23+
import type {
24+
AccessibilityState,
25+
AccessibilityActionEvent,
26+
AccessibilityActionInfo,
27+
} from './View/ViewAccessibility';
2428
import type {PressEvent} from '../Types/CoreEventTypes';
2529

2630
type ButtonProps = $ReadOnly<{|
@@ -137,6 +141,9 @@ type ButtonProps = $ReadOnly<{|
137141
/**
138142
* Accessibility props.
139143
*/
144+
accessible?: ?boolean,
145+
accessibilityActions?: ?$ReadOnlyArray<AccessibilityActionInfo>,
146+
onAccessibilityAction?: ?(event: AccessibilityActionEvent) => mixed,
140147
accessibilityState?: ?AccessibilityState,
141148
|}>;
142149

@@ -266,6 +273,9 @@ class Button extends React.Component<ButtonProps> {
266273
nextFocusRight,
267274
nextFocusUp,
268275
testID,
276+
accessible,
277+
accessibilityActions,
278+
onAccessibilityAction,
269279
} = this.props;
270280
const buttonStyles = [styles.button];
271281
const textStyles = [styles.text];
@@ -303,6 +313,9 @@ class Button extends React.Component<ButtonProps> {
303313

304314
return (
305315
<Touchable
316+
accessible={accessible}
317+
accessibilityActions={accessibilityActions}
318+
onAccessibilityAction={onAccessibilityAction}
306319
accessibilityLabel={accessibilityLabel}
307320
accessibilityRole="button"
308321
accessibilityState={accessibilityState}

Libraries/Components/Picker/Picker.js

+26
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,11 @@ import UnimplementedView from '../UnimplementedViews/UnimplementedView';
1818

1919
import type {TextStyleProp, ColorValue} from '../../StyleSheet/StyleSheet';
2020

21+
import type {
22+
AccessibilityActionEvent,
23+
AccessibilityActionInfo,
24+
} from '../View/ViewAccessibility';
25+
2126
const MODE_DIALOG = 'dialog';
2227
const MODE_DROPDOWN = 'dropdown';
2328

@@ -115,6 +120,27 @@ type PickerProps = $ReadOnly<{|
115120
* The string used for the accessibility label. Will be read once focused on the picker but not on change.
116121
*/
117122
accessibilityLabel?: ?string,
123+
124+
/**
125+
* When `true`, indicates that the view is an accessibility element.
126+
* By default, all the touchable elements are accessible.
127+
*
128+
* See https://reactnative.dev/docs/view.html#accessible
129+
*/
130+
accessible?: ?boolean,
131+
132+
/**
133+
* Provides an array of custom actions available for accessibility.
134+
*
135+
*/
136+
accessibilityActions?: ?$ReadOnlyArray<AccessibilityActionInfo>,
137+
138+
/**
139+
* When `accessible` is true, the system will try to invoke this function
140+
* when the user performs an accessibility custom action.
141+
*
142+
*/
143+
onAccessibilityAction?: ?(event: AccessibilityActionEvent) => mixed,
118144
|}>;
119145

120146
/**

Libraries/Components/Picker/PickerAndroid.android.js

+11
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,11 @@ import StyleSheet from '../../StyleSheet/StyleSheet';
1919
import invariant from 'invariant';
2020
import processColor from '../../StyleSheet/processColor';
2121

22+
import type {
23+
AccessibilityActionEvent,
24+
AccessibilityActionInfo,
25+
} from '../View/ViewAccessibility';
26+
2227
import type {SyntheticEvent} from '../../Types/CoreEventTypes';
2328
import type {ColorValue, TextStyleProp} from '../../StyleSheet/StyleSheet';
2429

@@ -31,6 +36,9 @@ type PickerItemSelectSyntheticEvent = SyntheticEvent<
3136
type PickerItemValue = number | string;
3237

3338
type Props = $ReadOnly<{|
39+
accessible?: ?boolean,
40+
accessibilityActions?: ?$ReadOnlyArray<AccessibilityActionInfo>,
41+
onAccessibilityAction?: ?(event: AccessibilityActionEvent) => mixed,
3442
accessibilityLabel?: ?Stringish,
3543
children?: React.Node,
3644
style?: ?TextStyleProp,
@@ -111,6 +119,9 @@ function PickerAndroid(props: Props): React.Node {
111119
);
112120

113121
const rootProps = {
122+
accessible: props.accessible,
123+
accessibilityActions: props.accessibilityActions,
124+
onAccessibilityAction: props.onAccessibilityAction,
114125
accessibilityLabel: props.accessibilityLabel,
115126
enabled: props.enabled,
116127
items,

Libraries/Text/TextProps.js

+4
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ import type {TextStyleProp} from '../StyleSheet/StyleSheet';
2020
import type {
2121
AccessibilityRole,
2222
AccessibilityState,
23+
AccessibilityActionInfo,
24+
AccessibilityActionEvent,
2325
} from '../Components/View/ViewAccessibility';
2426

2527
export type PressRetentionOffset = $ReadOnly<{|
@@ -39,6 +41,8 @@ export type TextProps = $ReadOnly<{|
3941
* See https://reactnative.dev/docs/text.html#accessible
4042
*/
4143
accessible?: ?boolean,
44+
accessibilityActions?: ?$ReadOnlyArray<AccessibilityActionInfo>,
45+
onAccessibilityAction?: ?(event: AccessibilityActionEvent) => mixed,
4246
accessibilityHint?: ?Stringish,
4347
accessibilityLabel?: ?Stringish,
4448
accessibilityRole?: ?AccessibilityRole,

packages/rn-tester/js/examples/Accessibility/AccessibilityExample.js

+66-1
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ const {
2323
Alert,
2424
StyleSheet,
2525
Slider,
26+
Picker,
2627
Platform,
2728
} = require('react-native');
2829
import type {EventSubscription} from 'react-native/Libraries/vendor/emitter/EventEmitter';
@@ -664,7 +665,7 @@ class AccessibilityActionsExample extends React.Component<{}> {
664665
</View>
665666
</RNTesterBlock>
666667

667-
<RNTesterBlock title="Button with custom accessibility actions">
668+
<RNTesterBlock title="TouchableWithoutFeedback with custom accessibility actions">
668669
<TouchableWithoutFeedback
669670
accessible={true}
670671
accessibilityActions={[
@@ -692,6 +693,70 @@ class AccessibilityActionsExample extends React.Component<{}> {
692693
</View>
693694
</TouchableWithoutFeedback>
694695
</RNTesterBlock>
696+
697+
<RNTesterBlock title="Button with accessibility actions">
698+
<Button
699+
accessible={true}
700+
accessibilityActions={[
701+
{name: 'activate', label: 'activate label'},
702+
{name: 'copy', label: 'copy label'},
703+
]}
704+
onAccessibilityAction={event => {
705+
switch (event.nativeEvent.actionName) {
706+
case 'activate':
707+
Alert.alert('Alert', 'Activate accessiblity action');
708+
break;
709+
case 'copy':
710+
Alert.alert('Alert', 'copy action success');
711+
break;
712+
}
713+
}}
714+
onPress={() => Alert.alert('Button has been pressed!')}
715+
title="Button with accessiblity action"
716+
/>
717+
</RNTesterBlock>
718+
719+
<RNTesterBlock title="Text with custom accessibility actions">
720+
<Text
721+
accessible={true}
722+
accessibilityActions={[
723+
{name: 'activate', label: 'activate label'},
724+
{name: 'copy', label: 'copy label'},
725+
]}
726+
onAccessibilityAction={event => {
727+
switch (event.nativeEvent.actionName) {
728+
case 'activate':
729+
Alert.alert('Alert', 'Activate accessiblity action');
730+
break;
731+
case 'copy':
732+
Alert.alert('Alert', 'copy action success');
733+
break;
734+
}
735+
}}>
736+
Text
737+
</Text>
738+
</RNTesterBlock>
739+
740+
<RNTesterBlock title="Picker with accessibility actions">
741+
<Picker
742+
accessible={true}
743+
accessibilityActions={[
744+
{name: 'activate', label: 'activate label'},
745+
{name: 'copy', label: 'copy label'},
746+
]}
747+
onAccessibilityAction={event => {
748+
switch (event.nativeEvent.actionName) {
749+
case 'activate':
750+
Alert.alert('Alert', 'Activate accessiblity action');
751+
break;
752+
case 'copy':
753+
Alert.alert('Alert', 'copy action success');
754+
break;
755+
}
756+
}}>
757+
<Picker.Item label="Item 1" value="item1" />
758+
</Picker>
759+
</RNTesterBlock>
695760
</View>
696761
);
697762
}

0 commit comments

Comments
 (0)