diff --git a/src/components/RadioButton/RadioButtonItem.tsx b/src/components/RadioButton/RadioButtonItem.tsx index e37ed435e2..0a737705ec 100644 --- a/src/components/RadioButton/RadioButtonItem.tsx +++ b/src/components/RadioButton/RadioButtonItem.tsx @@ -165,7 +165,16 @@ const RadioButtonItem = ({ color, theme, uncheckedColor, - }; + // The outer TouchableRipple in RadioButtonItem already provides the + // interactive surface. Hide the inner RadioButton from the + // accessibility tree so screen readers only encounter one control, + // and keep tabIndex: -1 so web keyboard users have a single + // tabstop per row (matches the approach used in Checkbox.Item). + focusable: false, + tabIndex: -1, + accessible: false, + 'aria-hidden': true, + } as const; const isLeading = position === 'leading'; let radioButton: any; diff --git a/src/components/__tests__/RadioButton/RadioButtonItem.test.tsx b/src/components/__tests__/RadioButton/RadioButtonItem.test.tsx index 821d9ebc5b..272f99e011 100644 --- a/src/components/__tests__/RadioButton/RadioButtonItem.test.tsx +++ b/src/components/__tests__/RadioButton/RadioButtonItem.test.tsx @@ -84,3 +84,16 @@ it('should execute onLongPress', async () => { expect(onLongPress).toHaveBeenCalledTimes(1); }); + +it('exposes only one radio control to screen readers', async () => { + await render( + + ); + + expect(screen.getAllByRole('radio')).toHaveLength(1); +}); + diff --git a/src/components/__tests__/RadioButton/__snapshots__/RadioButtonItem.test.tsx.snap b/src/components/__tests__/RadioButton/__snapshots__/RadioButtonItem.test.tsx.snap index 5867b1408c..280c367331 100644 --- a/src/components/__tests__/RadioButton/__snapshots__/RadioButtonItem.test.tsx.snap +++ b/src/components/__tests__/RadioButton/__snapshots__/RadioButtonItem.test.tsx.snap @@ -74,9 +74,10 @@ exports[`can render leading radio button control 1`] = ` "text": undefined, } } - accessible={true} + accessible={false} + aria-hidden={true} collapsable={false} - focusable={true} + focusable={false} onBlur={[Function]} onClick={[Function]} onFocus={[Function]} @@ -288,9 +289,10 @@ exports[`can render the Android radio button on different platforms 1`] = ` "text": undefined, } } - accessible={true} + accessible={false} + aria-hidden={true} collapsable={false} - focusable={true} + focusable={false} onBlur={[Function]} onClick={[Function]} onFocus={[Function]} @@ -440,9 +442,10 @@ exports[`can render the iOS radio button on different platforms 1`] = ` "text": undefined, } } - accessible={true} + accessible={false} + aria-hidden={true} collapsable={false} - focusable={true} + focusable={false} onBlur={[Function]} onClick={[Function]} onFocus={[Function]} @@ -618,9 +621,10 @@ exports[`renders unchecked 1`] = ` "text": undefined, } } - accessible={true} + accessible={false} + aria-hidden={true} collapsable={false} - focusable={true} + focusable={false} onBlur={[Function]} onClick={[Function]} onFocus={[Function]}