feat: add accessibility support (#117)

* chore: added accessibility base support

* chore: updated backdrop to avoid covering whole screen when its invisible

* chore: remove unused comments
This commit is contained in:
Mo Gorhom
2020-12-16 19:45:57 +01:00
committed by GitHub
parent d78f2202de
commit bfb7a8e362
3 changed files with 69 additions and 19 deletions

View File

@@ -9,7 +9,7 @@ import React, {
useLayoutEffect,
useEffect,
} from 'react';
import { ViewStyle } from 'react-native';
import { ViewStyle, AccessibilityInfo } from 'react-native';
import isEqual from 'lodash.isequal';
import invariant from 'invariant';
import Animated, {
@@ -486,6 +486,28 @@ const BottomSheetComponent = forwardRef<BottomSheet, BottomSheetProps>(
) {
return;
}
/**
* Here we announce the bottom sheet position
* for accessibility service.
*/
AccessibilityInfo.isScreenReaderEnabled().then(isEnabled => {
if (!isEnabled) {
return;
}
const positionInScreen = Math.max(
Math.floor(
((WINDOW_HEIGHT - snapPoints[currentPositionIndex] || 1) /
WINDOW_HEIGHT) *
100
),
0
).toFixed(0);
AccessibilityInfo.announceForAccessibility(
`Bottom sheet snapped to ${positionInScreen}% of the screen`
);
});
currentIndexRef.current = currentPositionIndex;
refreshUIElements();
handleOnChange(currentPositionIndex);
@@ -536,7 +558,12 @@ const BottomSheetComponent = forwardRef<BottomSheet, BottomSheetProps>(
ref={containerTapGestureRef}
{...containerTapGestureHandler}
>
<Animated.View style={containerStyle}>
<Animated.View
accessible={true}
accessibilityRole="adjustable"
accessibilityLabel="Bottom Sheet"
style={containerStyle}
>
<BottomSheetInternalProvider value={internalContextVariables}>
<BottomSheetBackgroundContainer
key="BottomSheetBackgroundContainer"

View File

@@ -20,6 +20,7 @@ import {
DEFAULT_ENABLE_TOUCH_THROUGH,
DEFAULT_CLOSE_ON_PRESS,
} from './constants';
import { WINDOW_HEIGHT } from '../../constants';
import type { BottomSheetDefaultBackdropProps } from './types';
import { styles } from './styles';
@@ -29,6 +30,10 @@ const {
} = require('react-native-reanimated');
const interpolate = interpolateV2 || interpolateV1;
const AnimatedTouchableWithoutFeedback = Animated.createAnimatedComponent(
TouchableWithoutFeedback
);
const BottomSheetBackdropComponent = ({
animatedIndex,
animatedPosition,
@@ -70,6 +75,15 @@ const BottomSheetBackdropComponent = ({
//#endregion
//#region styles
const buttonStyle = useMemo(
() => [
style,
{
top: cond(eq(animatedIndex, disappearsOnIndex), WINDOW_HEIGHT, 0),
},
],
[disappearsOnIndex, style, animatedIndex]
);
const containerStyle = useMemo(
() => [
style,
@@ -81,20 +95,22 @@ const BottomSheetBackdropComponent = ({
[style, animatedOpacity]
);
//#endregion
//#region effects
//#endregion
return closeOnPress ? (
<>
<TouchableWithoutFeedback onPress={handleOnPress} style={style}>
<AnimatedTouchableWithoutFeedback
accessible={true}
accessibilityRole="button"
accessibilityLabel="Bottom Sheet backdrop"
accessibilityHint="Tap to close the Bottom Sheet"
onPress={handleOnPress}
style={buttonStyle}
>
<Animated.View ref={containerRef} style={containerStyle} />
</TouchableWithoutFeedback>
</AnimatedTouchableWithoutFeedback>
<Animated.Code>
{() =>
cond(
and(eq(animatedPosition, 0), isTouchable),
and(eq(animatedPosition, disappearsOnIndex), isTouchable),
[
set(isTouchable, 0),
call([], () => {
@@ -104,15 +120,18 @@ const BottomSheetBackdropComponent = ({
});
}),
],
cond(and(neq(animatedPosition, 0), not(isTouchable)), [
set(isTouchable, 1),
call([], () => {
// @ts-ignore
containerRef.current.setNativeProps({
pointerEvents: 'auto',
});
}),
])
cond(
and(neq(animatedPosition, disappearsOnIndex), not(isTouchable)),
[
set(isTouchable, 1),
call([], () => {
// @ts-ignore
containerRef.current.setNativeProps({
pointerEvents: 'auto',
});
}),
]
)
)
}
</Animated.Code>

View File

@@ -68,6 +68,10 @@ const BottomSheetHandleContainerComponent = ({
onHandlerStateChange={onHandlerStateChange}
>
<Animated.View
accessible={true}
accessibilityRole="adjustable"
accessibilityLabel="Bottom Sheet handle"
accessibilityHint="Drag up or down to extend or minimize the Bottom Sheet"
onLayout={shouldMeasureHeight ? handleOnLayout : undefined}
>
{renderHandle()}