mirror of
https://github.com/zhigang1992/react-native-bottom-sheet.git
synced 2026-01-12 22:50:12 +08:00
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:
@@ -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"
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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()}
|
||||
|
||||
Reference in New Issue
Block a user