Accept tabIndex on <RadioGroup> component (#3646)

This PR allows you to pass a `tabIndex` to the `<RadioGroup>` component
and it will internally pass it down to the correct `<Radio />` or
`<RadioGroupOption>` component.

The reason we do it this way is because only a single radio should be
focusable (moving between radios can be done via the arrow keys instead
of the tab key).
This commit is contained in:
Robin Malfait
2025-02-21 16:27:32 +01:00
committed by GitHub
parent 466bb07ba6
commit 20f46dd9e8
2 changed files with 16 additions and 13 deletions
@@ -100,6 +100,7 @@ let RadioGroupDataContext = createContext<
containsCheckedOption: boolean
disabled: boolean
compare(a: unknown, z: unknown): boolean
tabIndex: number
} & StateDefinition)
| null
>(null)
@@ -178,6 +179,7 @@ function RadioGroupFn<TTag extends ElementType = typeof DEFAULT_RADIO_GROUP_TAG,
by,
disabled = providedDisabled || false,
defaultValue: _defaultValue,
tabIndex = 0,
...theirProps
} = props
let compare = useByComparator(by)
@@ -285,8 +287,8 @@ function RadioGroupFn<TTag extends ElementType = typeof DEFAULT_RADIO_GROUP_TAG,
})
let radioGroupData = useMemo<_Data>(
() => ({ value, firstOption, containsCheckedOption, disabled, compare, ...state }),
[value, firstOption, containsCheckedOption, disabled, compare, state]
() => ({ value, firstOption, containsCheckedOption, disabled, compare, tabIndex, ...state }),
[value, firstOption, containsCheckedOption, disabled, compare, tabIndex, state]
)
let radioGroupActions = useMemo<_Actions>(
() => ({ registerOption, change: triggerChange }),
@@ -424,8 +426,8 @@ function OptionFn<
'aria-disabled': disabled ? true : undefined,
tabIndex: (() => {
if (disabled) return -1
if (checked) return 0
if (!data.containsCheckedOption && isFirstOption) return 0
if (checked) return data.tabIndex
if (!data.containsCheckedOption && isFirstOption) return data.tabIndex
return -1
})(),
onClick: disabled ? undefined : handleClick,
@@ -547,8 +549,8 @@ function RadioFn<
'aria-disabled': disabled ? true : undefined,
tabIndex: (() => {
if (disabled) return -1
if (checked) return 0
if (!data.containsCheckedOption && isFirstOption) return 0
if (checked) return data.tabIndex
if (!data.containsCheckedOption && isFirstOption) return data.tabIndex
return -1
})(),
autoFocus,