Radio Group
Single-selection radio buttons with roving focus, typeahead, vim-style navigation, and form integration.
import * as RadioGroup from '@gentleduck/primitives/radio-group'import * as RadioGroup from '@gentleduck/primitives/radio-group'Anatomy
<RadioGroup.Root>
<RadioGroup.Item value="comfortable">
<RadioGroup.Indicator />
</RadioGroup.Item>
</RadioGroup.Root><RadioGroup.Root>
<RadioGroup.Item value="comfortable">
<RadioGroup.Indicator />
</RadioGroup.Item>
</RadioGroup.Root>Example
import * as RadioGroup from '@gentleduck/primitives/radio-group'
function DensityPicker() {
return (
<RadioGroup.Root defaultValue="comfortable" name="density" className="grid gap-2">
<RadioGroup.Item value="compact" textValue="Compact" aria-label="Compact density">
<RadioGroup.Indicator />
</RadioGroup.Item>
<RadioGroup.Item value="comfortable" textValue="Comfortable" aria-label="Comfortable density">
<RadioGroup.Indicator />
</RadioGroup.Item>
<RadioGroup.Item value="spacious" textValue="Spacious" aria-label="Spacious density">
<RadioGroup.Indicator />
</RadioGroup.Item>
</RadioGroup.Root>
)
}import * as RadioGroup from '@gentleduck/primitives/radio-group'
function DensityPicker() {
return (
<RadioGroup.Root defaultValue="comfortable" name="density" className="grid gap-2">
<RadioGroup.Item value="compact" textValue="Compact" aria-label="Compact density">
<RadioGroup.Indicator />
</RadioGroup.Item>
<RadioGroup.Item value="comfortable" textValue="Comfortable" aria-label="Comfortable density">
<RadioGroup.Indicator />
</RadioGroup.Item>
<RadioGroup.Item value="spacious" textValue="Spacious" aria-label="Spacious density">
<RadioGroup.Indicator />
</RadioGroup.Item>
</RadioGroup.Root>
)
}API
RadioGroup.Root
Container for a single-selection radio set. Uses roving focus and form-compatible hidden radio inputs.
| Prop | Type | Default | Description |
|---|---|---|---|
value | string | -- | Controlled selected value |
defaultValue | string | -- | Initial selected value (uncontrolled) |
onValueChange | (value: string) => void | -- | Called when selected value changes |
disabled | boolean | false | Disables all items in the group |
required | boolean | false | Marks the group required for form validation |
name | string | -- | Name used for hidden native radio inputs |
dir | 'ltr' | 'rtl' | -- | Text direction. Resolved with useDirection (dir prop -> DirectionProvider -> 'ltr'). |
orientation | 'horizontal' | 'vertical' | -- | Limits arrow-key navigation axis |
loop | boolean | true | Wraps focus from end to start (and reverse) |
...props | React.ComponentPropsWithoutRef<'div'> | -- | Additional props for the radiogroup container |
RadioGroup.Item
A single radio control. Renders a button with role="radio" and associated state data attributes.
| Prop | Type | Default | Description |
|---|---|---|---|
value | string | (required) | Unique value for the item |
textValue | string | -- | Optional text override used for typeahead matching |
disabled | boolean | false | Disables this item |
...props | React.ComponentPropsWithoutRef<'button'> | -- | Additional props for the radio button element |
RadioGroup.Indicator
Indicator content that mounts when the parent item is checked.
| Prop | Type | Default | Description |
|---|---|---|---|
forceMount | true | -- | Force indicator to stay mounted for animation control |
...props | React.ComponentPropsWithoutRef<'span'> | -- | Additional props for the indicator element |
Keyboard interactions
| Key | Action |
|---|---|
| ArrowUp / ArrowLeft | Move focus to previous item and select it |
| ArrowDown / ArrowRight | Move focus to next item and select it |
| Home / PageUp | Move to first item and select it |
| End / PageDown | Move to last item and select it |
| a-z | Typeahead jump to matching item and select it |
| g g | Jump to first item and select it |
Shift+g (G) | Jump to last item and select it |
| Space | Select focused item |