Skip to content

Commit

Permalink
feat: Improvements to Android accessibility (#168)
Browse files Browse the repository at this point in the history
  • Loading branch information
sfuqua authored May 19, 2020
1 parent b95117a commit b605fb8
Show file tree
Hide file tree
Showing 4 changed files with 59 additions and 7 deletions.
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 | |
Expand All @@ -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.

Expand Down
37 changes: 36 additions & 1 deletion src/ActionSheet/ActionGroup.tsx
Original file line number Diff line number Diff line change
@@ -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';

Expand All @@ -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,
Expand Down Expand Up @@ -80,6 +112,7 @@ export default class ActionGroup extends React.Component<Props> {
length,
textStyle,
tintColor,
autoFocus,
showSeparators,
} = this.props;
const optionViews: React.ReactNode[] = [];
Expand All @@ -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>
Expand Down
23 changes: 17 additions & 6 deletions src/ActionSheet/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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}
Expand Down Expand Up @@ -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={[
Expand Down Expand Up @@ -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}
Expand Down Expand Up @@ -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,
Expand Down
1 change: 1 addition & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ export interface ActionSheetOptions extends ActionSheetIOSOptions {
textStyle?: TextStyle;
titleTextStyle?: TextStyle;
messageTextStyle?: TextStyle;
autoFocus?: boolean;
showSeparators?: boolean;
containerStyle?: ViewStyle;
separatorStyle?: ViewStyle;
Expand Down

0 comments on commit b605fb8

Please sign in to comment.