11import React , { useEffect } from 'react' ;
22import {
3+ AccessibilityRole ,
4+ AccessibilityState ,
5+ AccessibilityValue ,
36 Pressable ,
47 StyleSheet ,
58 Text ,
@@ -14,11 +17,20 @@ import Animated, {
1417} from 'react-native-reanimated' ;
1518import { widthPercentageToDP } from 'react-native-responsive-screen' ;
1619
17- interface SegmentedControlProps {
20+ export interface Segment {
21+ label : string ;
22+ accessibilityLabel ?: string ;
23+ accessibilityHint ?: string ;
24+ accessibilityRole ?: AccessibilityRole ;
25+ accessibilityState ?: AccessibilityState ;
26+ accessibilityValue ?: AccessibilityValue ;
27+ }
28+
29+ export interface SegmentedControlProps {
1830 /**
19- * The Segments Text Array
31+ * An array of Segments. Can be a mix of strings for the Segment labels, or an object with a `label` and accessibility props.
2032 */
21- segments : Array < string > ;
33+ segments : Array < string | Segment > ;
2234 /**
2335 * The Current Active Segment Index
2436 */
@@ -115,6 +127,14 @@ const SegmentedControl: React.FC<SegmentedControlProps> = ({
115127 const translateValue = width / segments . length ;
116128 const tabTranslateValue = useSharedValue ( 0 ) ;
117129
130+ // Transform and memoize all segments into a `Segment` array.
131+ // This allows for the segments to be transformed only when they change, and to be treated as `Segment` on render.
132+ const memoizedSegments = React . useMemo < Segment [ ] > ( ( ) => {
133+ return segments . map ( ( segment ) =>
134+ typeof segment === 'string' ? { label : segment } : segment
135+ ) ;
136+ } , [ segments ] ) ;
137+
118138 // useCallBack with an empty array as input, which will call inner lambda only once and memoize the reference for future calls
119139 const memoizedTabPressCallback = React . useCallback (
120140 ( index ) => {
@@ -193,12 +213,22 @@ const SegmentedControl: React.FC<SegmentedControlProps> = ({
193213 tabTranslateAnimatedStyles ,
194214 ] }
195215 />
196- { segments . map ( ( segment , index ) => {
216+ { memoizedSegments . map ( ( segment , index ) => {
217+ const isSelected = currentIndex === index ;
218+ const { label, ...accessibilityProps } = segment ;
219+
197220 return (
198221 < Pressable
199222 onPress = { ( ) => memoizedTabPressCallback ( index ) }
200223 key = { index }
201224 style = { [ styles . touchableContainer , pressableWrapper ] }
225+ accessibilityState = { { selected : isSelected } }
226+ accessibilityHint = { ! isSelected ? `Selects ${ label } option` : '' }
227+ accessibilityLabel = { `${ label } , option, ${ index + 1 } of ${
228+ segments . length
229+ } `}
230+ accessibilityRole = "button"
231+ { ...accessibilityProps }
202232 >
203233 < View style = { styles . textWrapper } >
204234 < Text
@@ -208,7 +238,7 @@ const SegmentedControl: React.FC<SegmentedControlProps> = ({
208238 : finalisedInActiveTextStyle ,
209239 ] }
210240 >
211- { segment }
241+ { label }
212242 </ Text >
213243 { typeof badgeValues [ index ] === 'number' && (
214244 < View
0 commit comments