feat: Improvements to Android accessibility (#168)

This commit is contained in:
Steven Fuqua authored and GitHub committed 2020-05-19 07:48:58 -05:00
1 parent b95117a8cd
commit b605fb8a3b
4 files changed
+59 -7

No files matched your search

+5
View File
@@ -117,6 +117,7 @@ The below props allow modification of the Android ActionSheet. They have no effe
| textStyle | TextStyle | No | |
| titleTextStyle | TextStyle | No | |
| messageTextStyle | TextStyle | No | |
| autoFocus | boolean | No | false |
| showSeparators | boolean | No | false |
| containerStyle | ViewStyle | No | |
| separatorStyle | ViewStyle | No | |
@@ -138,6 +139,10 @@ Apply any text style props to the title if present.
#### `messageTextStyle` (optional)
Apply any text style props to the message if present.
#### `autoFocus`: (optional)
If true, will give the first option screen reader focus automatically when the action sheet becomes visible.
On iOS, this is the default behavior of the native action sheet.
#### `showSeparators`: (optional)
Show separators between items. On iOS, separators always show so this prop has no effect.
+36 -1
View File
@@ -1,5 +1,15 @@
import * as React from 'react';
import { StyleSheet, Text, Image, View, ScrollView } from 'react-native';
import {
StyleSheet,
Text,
Image,
View,
ScrollView,
findNodeHandle,
AccessibilityInfo,
Platform,
UIManager,
} from 'react-native';
import TouchableNativeFeedbackSafe from './TouchableNativeFeedbackSafe';
import { ActionSheetOptions } from '../types';
@@ -14,6 +24,28 @@ const BLACK_54PC_TRANSPARENT = '#0000008a';
const BLACK_87PC_TRANSPARENT = '#000000de';
const DESTRUCTIVE_COLOR = '#d32f2f';
/**
* Can be used as a React ref for a component to auto-focus for accessibility on render.
* @param ref The component to auto-focus
*/
const focusViewOnRender = (ref: React.Component | null) => {
if (ref) {
const reactTag = findNodeHandle(ref);
if (reactTag) {
if (Platform.OS === 'android') {
// @ts-ignore: sendAccessibilityEvent is missing from @types/react-native
UIManager.sendAccessibilityEvent(
reactTag,
// @ts-ignore: AccessibilityEventTypes is missing from @types/react-native
UIManager.AccessibilityEventTypes.typeViewFocused
);
} else {
AccessibilityInfo.setAccessibilityFocus(reactTag);
}
}
}
};
export default class ActionGroup extends React.Component<Props> {
static defaultProps = {
title: null,
@@ -80,6 +112,7 @@ export default class ActionGroup extends React.Component<Props> {
length,
textStyle,
tintColor,
autoFocus,
showSeparators,
} = this.props;
const optionViews: React.ReactNode[] = [];
@@ -97,11 +130,13 @@ export default class ActionGroup extends React.Component<Props> {
optionViews.push(
<TouchableNativeFeedbackSafe
ref={autoFocus && i === 0 ? focusViewOnRender : undefined}
key={i}
pressInDelay={0}
background={nativeFeedbackBackground}
onPress={() => onSelect(i)}
style={styles.button}
accessibilityRole="button"
accessibilityLabel={options[i]}>
{this._renderIconElement(iconSource, color)}
<Text style={[styles.text, textStyle, { color }]}>{options[i]}</Text>
+17 -6
View File
@@ -66,13 +66,19 @@ export default class ActionSheet extends React.Component<Props, State> {
]}
/>
) : null;
return (
// While the sheet is visible, hide the rest of the app's content from screen readers.
const appContent = (
<View
pointerEvents={this.props.pointerEvents}
style={{
flex: 1,
}}>
style={styles.flexContainer}
importantForAccessibility={isVisible ? 'no-hide-descendants' : 'auto'}>
{React.Children.only(this.props.children)}
</View>
);
return (
<View pointerEvents={this.props.pointerEvents} style={styles.flexContainer}>
{appContent}
{isVisible && !useModal && (
<React.Fragment>
{overlay}
@@ -107,12 +113,13 @@ export default class ActionSheet extends React.Component<Props, State> {
titleTextStyle,
message,
messageTextStyle,
autoFocus,
showSeparators,
containerStyle,
separatorStyle,
} = options;
return (
<TouchableWithoutFeedback onPress={this._selectCancelButton}>
<TouchableWithoutFeedback importantForAccessibility="yes" onPress={this._selectCancelButton}>
<Animated.View
needsOffscreenAlphaCompositing={isAnimating}
style={[
@@ -144,6 +151,7 @@ export default class ActionSheet extends React.Component<Props, State> {
titleTextStyle={titleTextStyle}
message={message || undefined}
messageTextStyle={messageTextStyle}
autoFocus={autoFocus}
showSeparators={showSeparators}
containerStyle={containerStyle}
separatorStyle={separatorStyle}
@@ -264,6 +272,9 @@ export default class ActionSheet extends React.Component<Props, State> {
}
const styles = StyleSheet.create({
flexContainer: {
flex: 1,
},
overlay: {
position: 'absolute',
top: 0,
+1
View File
@@ -23,6 +23,7 @@ export interface ActionSheetOptions extends ActionSheetIOSOptions {
textStyle?: TextStyle;
titleTextStyle?: TextStyle;
messageTextStyle?: TextStyle;
autoFocus?: boolean;
showSeparators?: boolean;
containerStyle?: ViewStyle;
separatorStyle?: ViewStyle;