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.

Preview

No preview output yet.

live.tsxReady

Controlled

A compact radio group driven by value and onValueChange.

Preview

No preview output yet.

live.tsxReady

Radio Cards

A two-card plan selector with full-card radio targets.

Preview

No preview output yet.

live.tsxReady

Anatomy

tsx
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.

PropTypeDefault
value
string
defaultValue
string
onValueChange
(value: string) => void
disabled
booleanfalse
AttributeValues
role'radiogroup'
aria-activedescendantid of the selected Item
data-disabledpresent when the group is disabled

Item

Single radio option. Renders as a `<button role="radio">` and handles selection, keyboard navigation, and hidden form submission.

PropTypeDefault
value*
string
disabled
booleanfalse
name
string
required
booleanfalse
AttributeValues
role'radio'
aria-checkedtrue | false
aria-disabledtrue when disabled
data-state'checked' | 'unchecked'
data-disabledpresent 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.

AttributeValues
data-state'checked' | 'unchecked'
data-disabledpresent when the Item is disabled

Keyboard

ShortcutAction
TabMove focus into the group (lands on the selected Item, or the first enabled Item if none is selected).
Shift+TabMove focus out of the group to the previous focusable element.
SpaceSelect 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:

  • Root renders with role="radiogroup" and tracks the selected Item via aria-activedescendant.
  • Each Item renders as role="radio" with aria-checked reflecting 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.
  • disabled on Root disables the entire group; disabled on Item disables just that option while keeping it visible in the tab order.
  • When name is set on an Item, selection writes to a hidden <input> so the group participates in native form submission.
  • Provide a label via aria-label or aria-labelledby on Root so assistive tech can announce the group purpose.
Previous
Progress