RadioGroup
A group of mutually-exclusive options with roving tabindex.
Anatomy
import { RadioGroup } from "@spacing-ui/core";
<RadioGroup defaultValue="medium" onValueChange={(v) => console.log(v)}>
<RadioGroup.Item value="small">Small</RadioGroup.Item>
<RadioGroup.Item value="medium">Medium</RadioGroup.Item>
<RadioGroup.Item value="large">Large</RadioGroup.Item>
</RadioGroup>;API
RadioGroup (Root)
| Prop | Type | Default | Description |
|---|---|---|---|
value / defaultValue | string | — | |
onValueChange | (value: string) => void | — | |
name | string | auto-generated | Native form name |
disabled | boolean | false | |
orientation | "horizontal" | "vertical" | "vertical" |
Accessibility
role="radiogroup", items haverole="radio"- Roving tabindex: only the checked item (or first item) is in the tab order
- Keyboard: ArrowDown/Up (vertical) or ArrowRight/Left (horizontal)
Examples
Horizontal orientation
<RadioGroup defaultValue="left" orientation="horizontal">
<RadioGroup.Item value="left">Left</RadioGroup.Item>
<RadioGroup.Item value="center">Center</RadioGroup.Item>
<RadioGroup.Item value="right">Right</RadioGroup.Item>
</RadioGroup>Arrow keys follow orientation: Right/Left for horizontal, Up/Down for vertical.
Native form submission
<form action="/prefs" method="post">
<RadioGroup name="theme" defaultValue="system">
<RadioGroup.Item value="light">Light</RadioGroup.Item>
<RadioGroup.Item value="dark">Dark</RadioGroup.Item>
<RadioGroup.Item value="system">Match system</RadioGroup.Item>
</RadioGroup>
</form>Renders hidden native inputs so FormData picks up the selected value.
Live demo
Orientation & wrapping
The orientation prop only affects arrow-key handling — it doesn’t lay items out. Use your own CSS (flex row / column, grid) to visually match the arrow-key behavior.
Testing
const radios = screen.getAllByRole("radio");
await userEvent.click(radios[2]);
expect(radios[2]).toBeChecked();Last updated on