Skip to content

Commit 9e36684

Browse files
nitzanyizM-i-k-e-l
andauthored
TabBar - Better accessibility roles and instructions (#3501)
* Added selected and tab accessibility role --------- Co-authored-by: Miki Leib <38354019+M-i-k-e-l@users.noreply.github.com>
1 parent ff9568f commit 9e36684

File tree

2 files changed

+15
-3
lines changed

2 files changed

+15
-3
lines changed

src/components/tabController/TabBar.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -308,7 +308,7 @@ const TabBar = (props: Props) => {
308308
onContentSizeChange={onContentSizeChange}
309309
onLayout={onLayout}
310310
>
311-
<View style={tabBarContainerStyle}>{tabBarItems}</View>
311+
<View style={tabBarContainerStyle} accessibilityRole={Constants.isIOS ? 'tabbar' : 'tablist'} >{tabBarItems}</View>
312312
{itemsCount > 1 && (
313313
<Reanimated.View style={[styles.selectedIndicator, indicatorStyle, _indicatorTransitionStyle]}/>
314314
)}

src/components/tabController/TabBarItem.tsx

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
// TODO: support commented props
2-
import React, {useCallback, useContext, useEffect, useRef, useMemo, ReactElement} from 'react';
2+
import React, {useCallback, useContext, useEffect, useRef, useMemo, ReactElement, useState} from 'react';
33
import {StyleSheet, TextStyle, LayoutChangeEvent, StyleProp, ViewStyle, TextProps} from 'react-native';
44
import _ from 'lodash';
5-
import Reanimated, {runOnJS, useAnimatedStyle, useSharedValue} from 'react-native-reanimated';
5+
import Reanimated, {runOnJS, useAnimatedReaction, useAnimatedStyle, useSharedValue} from 'react-native-reanimated';
66
import {Gesture, GestureDetector} from 'react-native-gesture-handler';
77
import {Colors, Typography, Spacings} from '../../style';
88
import Badge, {BadgeProps} from '../badge';
@@ -144,6 +144,7 @@ export default function TabBarItem({
144144
// JSON.parse(JSON.stringify is due to an issue with reanimated
145145
const sharedLabelStyle = useSharedValue(JSON.parse(JSON.stringify(StyleSheet.flatten(labelStyle))));
146146
const sharedSelectedLabelStyle = useSharedValue(JSON.parse(JSON.stringify(StyleSheet.flatten(selectedLabelStyle))));
147+
const [isSelected, setIsSelected] = useState(currentPage.value === index);
147148

148149
// NOTE: We clone these color values in refs because they might contain a PlatformColor value
149150
// which throws an error (see https://github.com/software-mansion/react-native-reanimated/issues/3164)
@@ -157,6 +158,12 @@ export default function TabBarItem({
157158
}
158159
}, []);
159160

161+
useAnimatedReaction(() => currentPage.value === index, (isSelected, prevIsSelected) => {
162+
if (isSelected !== prevIsSelected) {
163+
runOnJS(setIsSelected)(isSelected);
164+
}
165+
});
166+
160167
const onLayout = useCallback((event: LayoutChangeEvent) => {
161168
const {width} = event.nativeEvent.layout;
162169

@@ -201,6 +208,8 @@ export default function TabBarItem({
201208
return [styles.tabItem, {flex}, style, constantWidthStyle, pressStyle];
202209
}, [style, spreadItems]);
203210

211+
const accessibilityState = useMemo(() => ({selected: isSelected}), [isSelected]);
212+
204213
const gesture = Gesture.Tap()
205214
.maxDuration(60000)
206215
.onEnd(() => {
@@ -226,6 +235,9 @@ export default function TabBarItem({
226235
style={_style}
227236
onLayout={onLayout}
228237
testID={testID}
238+
accessible
239+
accessibilityRole="tab"
240+
accessibilityState={accessibilityState}
229241
>
230242
{leadingAccessory}
231243
{icon && (

0 commit comments

Comments
 (0)