RadioGroup

4 parts

A set of mutually exclusive options where only one may be selected at a time, built on role="radiogroup" with full keyboard roving focus (arrow keys move and select, Space selects, Home/End and PageUp/PageDown jump to ends). The container and state owner: it tracks the selected value (controlled via v-model or uncontrolled via defaultValue), provides context to RadioGroupItem, and renders a hidden form input when name is set and the group lives inside a <form>. Values are not limited to strings — numbers, booleans, null, and plain objects are supported and compared structurally (override with by). Reach for it whenever a user must pick exactly one choice from a small, visible list.

Demo

Loading demo…

Anatomy

Import the parts and compose them. Each part forwards attributes to its underlying element.

vue
import {
  Radio,
  RadioGroupIndicator,
  RadioGroupItem,
  RadioGroupRoot,
} from '@robonen/primitives/forms/radio-group';

<RadioGroupRoot>
  <Radio />
  <RadioGroupIndicator />
  <RadioGroupItem />
</RadioGroupRoot>

API Reference

Radio

Radio

A standalone radio, usable on its own outside a `RadioGroupRoot`. It owns its own `checked` state (controlled via `v-model:checked` or uncontrolled), and — when given a `name` inside a `<form>` — renders a hidden native input so its value participates in form submission and native validation. Like `RadioGroupItem` it emits a cancelable `select` event before toggling; call `event.preventDefault()` to veto.

PropTypeDescription
id?stringElement id, also used to derive an aria-label from an associated <label for=id>.
value?AcceptableValueThe value submitted with the owning form when name is set.
disabled?booleanWhen true, the radio cannot be interacted with.
required?booleanMarks the radio as required for assistive tech and native validation.
name?stringName of the hidden form field submitted with the owning <form>.
checked?booleanTwo-way bound value (v-model:checked).
Emits
EventPayload
update:checked[value: boolean]

RadioGroupIndicator

Indicator

Renders its content only when the parent `RadioGroupItem` is selected, mirroring that state via `data-state`. Place the filled dot or check mark inside it. Wrapped in `Presence`, so it can animate out via CSS leave animations; use `forceMount` to keep it mounted for animation control.

PropTypeDescription
forceMount?booleanKeep the indicator mounted regardless of checked state (for exit animations / measuring).

RadioGroupItem

Item

A single selectable option within a `RadioGroupRoot`, rendered by default as a native `<button role="radio">`. Clicking, pressing Space, or arrow-keying onto it selects its `value`; it reflects selection via `data-state` and participates in the group's roving tab order. Provides context to a nested `RadioGroupIndicator`. Emits a cancelable `select` event before the value commits — call `event.preventDefault()` to veto the selection.

PropTypeDescription
valueTThe value this item represents — any structural value, not just strings.
disabled?booleanWhen true, the item cannot be selected or focused.
required?booleanMarks the item as required (merged with the group-level required).
id?stringAssociates a <label for=id>; its text becomes the radio's aria-label.

RadioGroupRoot

Root

A set of mutually exclusive options where only one may be selected at a time, built on `role="radiogroup"` with full keyboard roving focus (arrow keys move and select, Space selects, Home/End and PageUp/PageDown jump to ends). The container and state owner: it tracks the selected value (controlled via `v-model` or uncontrolled via `defaultValue`), provides context to `RadioGroupItem`, and renders a hidden form input when `name` is set and the group lives inside a `<form>`. Values are not limited to strings — numbers, booleans, `null`, and plain objects are supported and compared structurally (override with `by`). Reach for it whenever a user must pick exactly one choice from a small, visible list.

PropTypeDescription
defaultValue?TThe value of the radio item that should be checked when initially rendered (uncontrolled).
disabled?booleanWhen true, prevents the user from interacting with radio items.
required?booleanMarks the group, and every item, as required for assistive tech and native validation.
name?stringName of the hidden form field submitted with the owning <form>.
orientation?'horizontal' | 'vertical'The orientation arrow navigation follows.
dir?RovingDirectionReading direction. When omitted, inherits from the active ConfigProvider (falling back to 'ltr'), so an app-wide RTL setting flips arrow navigation.
loop?booleanWhen true, arrow navigation wraps from the last item to the first and vice versa.
by?RadioCompareByHow an item value is compared against the selected value. Omitted → structural deep equality; a function → custom comparator; a string → compare that property key.
modelValue?T | undefinedTwo-way bound value (v-model).
Emits
EventPayload
update:modelValue[value: T | undefined]