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:
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user