Inputs/Radio Group

Radio Group

A set of checkable buttons where only one can be checked at a time.

Themed

When to Use

Use Radio Group when you need to:

  • Present a set of mutually exclusive options where only one can be selected
  • Show all available options at once so users can compare before choosing
  • Collect a required single selection from a small set (2-7 options)
  • Allow users to change their selection freely before form submission
  • Display options with descriptions or additional context alongside each choice

When Not to Use

  • Multiple selections allowed - use Checkbox for independent choices
  • More than 7 options - use Select to save space with a dropdown
  • Binary on/off toggle - use Switch or Checkbox
  • Compact option selection in toolbars - use Toggle Group for visual button-style selection

Default

A vertical radio group with labels. Each option is paired with a Label using matching id/htmlFor attributes.

Disabled

Individual radio items can be disabled while keeping others interactive.

With Description

Radio items with labels and descriptive helper text for additional context.

Pay with your credit or debit card.

Pay with your PayPal account.

Pay with Apple Pay on supported devices.

Horizontal

Radio group with horizontal layout using flex for inline option selection.

Controlled

Controlled radio group with external state management via value and onValueChange.

Selected: option-one

Form Example

Radio group integrated into a form layout with a submit button.

UX & Design Guidelines

Visual Hierarchy

Place the most commonly selected or recommended option first in the list. Use descriptions beneath labels when options need additional context. Keep labels concise and parallel in grammatical structure. Consider using a default selection to reduce cognitive load when one option is clearly preferred.

Spacing & Layout

The default vertical layout uses gap-3 between items. For horizontal layouts, apply className="flex gap-4" to the RadioGroup. When including descriptions, increase spacing with className="grid gap-4" and align the radio indicator to the top using className="mt-1" on the RadioGroupItem.

Responsive Behavior

Vertical layout works well across all screen sizes. For horizontal layouts, consider switching to vertical on smaller screens using responsive classes like className="flex flex-col sm:flex-row gap-4". Radio items have a 16px (size-4) touch target for the indicator; pair with labels to expand the clickable area.

Color & Contrast

The radio indicator uses border-input for the unselected state and text-primary with fill-primary for the selected dot, ensuring clear visual differentiation. Disabled items reduce opacity to 50%. Invalid states use border-destructive with a subtle ring for form validation feedback.

Accessibility

Keyboard Navigation

  • Tab — Move focus into and out of the radio group
  • Arrow Down / Arrow Right — Move focus and selection to the next radio item
  • Arrow Up / Arrow Left — Move focus and selection to the previous radio item
  • Space — Select the focused radio item (if not already selected)

Screen Reader Support

  • The group uses role="radiogroup" and each item uses role="radio"
  • Each item announces its label, checked state, and position (e.g., "1 of 3")
  • Always pair each RadioGroupItem with a <Label> using matching id/htmlFor
  • Disabled items are announced as "dimmed" or "unavailable" by screen readers

Focus Management

Focus ring uses focus-visible:ring-[3px] with focus-visible:border-ring for clear visibility. Arrow keys move both focus and selection simultaneously (roving tabindex pattern). Focus wraps from the last item to the first and vice versa. Only one radio item in the group receives focus via Tab at a time.

ARIA Attributes

{/* Radio group with accessible label */}
<RadioGroup aria-label="Select a plan">
  <div className="flex items-center gap-3">
    <RadioGroupItem value="free" id="plan-free" />
    <Label htmlFor="plan-free">Free</Label>
  </div>
  <div className="flex items-center gap-3">
    <RadioGroupItem value="pro" id="plan-pro" />
    <Label htmlFor="plan-pro">Pro</Label>
  </div>
</RadioGroup>

{/* Radio group with aria-labelledby */}
<h3 id="plan-heading">Choose your plan</h3>
<RadioGroup aria-labelledby="plan-heading">
  <div className="flex items-center gap-3">
    <RadioGroupItem value="starter" id="starter" />
    <Label htmlFor="starter">Starter</Label>
  </div>
  <div className="flex items-center gap-3">
    <RadioGroupItem value="business" id="business" />
    <Label htmlFor="business">Business</Label>
  </div>
</RadioGroup>

{/* Required radio group */}
<RadioGroup required aria-label="Payment method">
  <div className="flex items-center gap-3">
    <RadioGroupItem value="card" id="pay-card" />
    <Label htmlFor="pay-card">Credit Card</Label>
  </div>
  <div className="flex items-center gap-3">
    <RadioGroupItem value="bank" id="pay-bank" />
    <Label htmlFor="pay-bank">Bank Transfer</Label>
  </div>
</RadioGroup>

API Reference

The RadioGroup component accepts the following props in addition to standard div attributes.

PropTypeDefaultDescription
valuestringThe controlled value of the selected radio item.
defaultValuestringThe default value when initially rendered (uncontrolled).
onValueChange(value: string) => voidEvent handler called when the value changes.
disabledbooleanfalseWhen true, prevents user interaction with all items.
requiredbooleanfalseWhen true, indicates a selection is required for form submission.
namestringThe name of the radio group for form submission.
orientation"horizontal" | "vertical""vertical"The orientation of the radio group for keyboard navigation.
classNamestringAdditional CSS classes to apply to the radio group container.

RadioGroupItem Props

Individual radio items within a radio group.

PropTypeDefaultDescription
valuerequiredstringA unique value for the item (required).
disabledbooleanfalseWhen true, prevents user interaction with this item.
idstringThe id for the radio item (used with Label htmlFor).
classNamestringAdditional CSS classes to apply to the radio item.