Radio
A headless, accessible radio group with roving tabindex, arrow-key selection, and native form support.
Features
- Accessible radio groups
- Controlled or uncontrolled
- Roving tabindex
- Item or group disabled state
- Native form integration
- Composable indicator
Installation
npm install @ariaui/radio
Examples
Three playgrounds: an uncontrolled group with a disabled option, the same layout controlled with useState, and full-card items for pricing-style selection.
Circular demos share class strings from radioExampleTokens.ts; choice cards keep gradient accents on the top bar.
Uncontrolled
A compact radio group using defaultValue.
No preview output yet.
Controlled
A compact radio group driven by value and onValueChange.
No preview output yet.
Radio Cards
A two-card plan selector with full-card radio targets.
No preview output yet.
Anatomy
import * as Radio from "@ariaui/radio";
export default function Example() {
return (
<Radio.Root>
<Radio.Item>
<Radio.Indicator />
</Radio.Item>
</Radio.Root>
);
}
API Reference
Root
Radiogroup container. Manages the selected value, roving tabindex across Items, and hidden form input submission when `name` is set on an Item.
| Prop | Type | Default |
|---|---|---|
value | string | — |
defaultValue | string | — |
onValueChange | (value: string) => void | — |
disabled | boolean | false |
| Attribute | Values |
|---|---|
| role | 'radiogroup' |
| aria-activedescendant | id of the selected Item |
| data-disabled | present when the group is disabled |
Item
Single radio option. Renders as a `<button role="radio">` and handles selection, keyboard navigation, and hidden form submission.
| Prop | Type | Default |
|---|---|---|
value* | string | — |
disabled | boolean | false |
name | string | — |
required | boolean | false |
| Attribute | Values |
|---|---|
| role | 'radio' |
| aria-checked | true | false |
| aria-disabled | true when disabled |
| data-state | 'checked' | 'unchecked' |
| data-disabled | present when disabled |
Indicator
Visual marker shown when the parent Item is checked. Bring your own icon — for example an SVG circle — and toggle it with the Item's `data-state` attribute.
| Attribute | Values |
|---|---|
| data-state | 'checked' | 'unchecked' |
| data-disabled | present when the Item is disabled |
Keyboard
| Shortcut | Action |
|---|---|
| Tab | Move focus into the group (lands on the selected Item, or the first enabled Item if none is selected). |
| Shift+Tab | Move focus out of the group to the previous focusable element. |
| Space | Select the focused Item. |
| ↓/→ | Move focus to and select the next enabled Item, wrapping to the start. |
| ↑/← | Move focus to and select the previous enabled Item, wrapping to the end. |
Accessibility
Radio follows the WAI-ARIA Radio Group pattern:
Rootrenders withrole="radiogroup"and tracks the selected Item viaaria-activedescendant.- Each
Itemrenders asrole="radio"witharia-checkedreflecting the current selection. - Tabbing into the group lands on the selected Item — or the first enabled Item when nothing is selected — so Tab never stops on every option.
- Arrow keys move selection and focus together, wrapping at the ends; Space selects the currently focused Item.
disabledon Root disables the entire group;disabledon Item disables just that option while keeping it visible in the tab order.- When
nameis set on an Item, selection writes to a hidden<input>so the group participates in native form submission. - Provide a label via
aria-labeloraria-labelledbyon Root so assistive tech can announce the group purpose.