Radio Group
A set of checkable buttons where only one can be checked at a time.
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 usesrole="radio" - Each item announces its label, checked state, and position (e.g., "1 of 3")
- Always pair each RadioGroupItem with a
<Label>using matchingid/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>Related Components
Checkbox
A control for toggling between checked and unchecked. Use when multiple selections are allowed.
Select
A dropdown list of options. Use when space is limited or there are many options.
Toggle Group
A group of toggle buttons for exclusive or multi-select options with a compact visual style.
Switch
A binary toggle for on/off states. Use instead of a two-option radio group.
API Reference
The RadioGroup component accepts the following props in addition to standard div attributes.
| Prop | Type | Default | Description |
|---|---|---|---|
| value | string | — | The controlled value of the selected radio item. |
| defaultValue | string | — | The default value when initially rendered (uncontrolled). |
| onValueChange | (value: string) => void | — | Event handler called when the value changes. |
| disabled | boolean | false | When true, prevents user interaction with all items. |
| required | boolean | false | When true, indicates a selection is required for form submission. |
| name | string | — | The name of the radio group for form submission. |
| orientation | "horizontal" | "vertical" | "vertical" | The orientation of the radio group for keyboard navigation. |
| className | string | — | Additional CSS classes to apply to the radio group container. |
RadioGroupItem Props
Individual radio items within a radio group.
| Prop | Type | Default | Description |
|---|---|---|---|
| valuerequired | string | — | A unique value for the item (required). |
| disabled | boolean | false | When true, prevents user interaction with this item. |
| id | string | — | The id for the radio item (used with Label htmlFor). |
| className | string | — | Additional CSS classes to apply to the radio item. |