RadioGroup

A group of radio buttons where only one option can be selected at a time. Built on the @base-ui/react RadioGroup primitive with circular indicators, expanded click targets, and managed selection state.

Anatomy

A <RadioGroup> container with a grid layout holds multiple <RadioGroupItem> elements. Each item renders as a circle with a centered indicator dot when selected. The group manages single-selection state automatically.

Examples

Vertical (default)

With disabled option

Design Guidelines

Do

  • Use for mutually exclusive options. When the user must pick exactly one option from a set.
  • Always pre-select a default. Radio groups should always have one option selected.
  • Keep options to 2-7 items. Longer lists should use a Select or Combobox instead.
  • Stack vertically. Vertical layout is easier to scan than horizontal.

Don't

  • Don't use for multiple selections. Use Checkbox for selecting multiple items.
  • Don't use for binary on/off. Use Switch for settings that take immediate effect.
  • Don't show without labels. Each radio needs descriptive text for accessibility.
  • Don't start without a selection. An empty radio group creates confusion.

Developer Reference

Accessibility

  • Uses Base UI RadioGroup — manages aria-checked and roving tabindex.
  • Arrow keys navigate between items; Space/Enter selects.
  • The indicator dot (size-2, white) appears centered on checked state.
  • After pseudo-element expands click target for WCAG touch target compliance.
  • aria-invalid triggers destructive ring on all items.

Usage

import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group"
import { Label } from "@/components/ui/label"

<RadioGroup defaultValue="comfortable">
  <div className="flex items-center gap-2">
    <RadioGroupItem value="default" id="r1" />
    <Label htmlFor="r1">Default</Label>
  </div>
  <div className="flex items-center gap-2">
    <RadioGroupItem value="comfortable" id="r2" />
    <Label htmlFor="r2">Comfortable</Label>
  </div>
  <div className="flex items-center gap-2">
    <RadioGroupItem value="compact" id="r3" />
    <Label htmlFor="r3">Compact</Label>
  </div>
</RadioGroup>

// Controlled
const [value, setValue] = useState("comfortable")
<RadioGroup value={value} onValueChange={setValue}>
  ...
</RadioGroup>