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
+8 -7
View File
@@ -7,15 +7,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]
### Fixed
- Use correct `ownerDocument` when using internal `<Portal/>` element ([#3594](https://github.com/tailwindlabs/headlessui/pull/3594))
- Bump `@tanstack/react-virtual` to be fix warnings in React 19 projects ([#3588](https://github.com/tailwindlabs/headlessui/pull/3588))
- Fix `aria-invalid` attributes to have a valid `'true'` value ([#3639](https://github.com/tailwindlabs/headlessui/pull/3639))
### Added
- Accept `tabIndex` on `Checkbox` component ([#3645](https://github.com/tailwindlabs/headlessui/pull/3645))
- Accept `tabIndex` on the `Checkbox` component ([#3645](https://github.com/tailwindlabs/headlessui/pull/3645))
- Accept `tabIndex` on the `RadioGroup` component ([#3646](https://github.com/tailwindlabs/headlessui/pull/3646))
### Fixed
- Use correct `ownerDocument` when using internal `Portal` component ([#3594](https://github.com/tailwindlabs/headlessui/pull/3594))
- Bump `@tanstack/react-virtual` to be fix warnings in React 19 projects ([#3588](https://github.com/tailwindlabs/headlessui/pull/3588))
- Fix `aria-invalid` attributes to have a valid `'true'` value ([#3639](https://github.com/tailwindlabs/headlessui/pull/3639))
## [2.2.0] - 2024-10-25
@@ -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,