Radio Group
Radio buttons allow users to select exactly one option from a set of mutually exclusive choices. Unlike Checkbox (multi-select) or Toggle (binary instant action), Radio Group is used when only one value can be selected and the options should all be visible at once.
When to Use
Use Radio when
- User must choose exactly one option from 2–6 visible choices
- All options need to be visible simultaneously for comparison
- Selection changes on form submit (not instant)
- Options are mutually exclusive
Don't use Radio when
- More than 6 options — use Select instead
- Multiple selections allowed — use Checkbox
- Instant toggle needed — use Toggle/Switch
Anatomy
1
Fieldset wrapper
Semantic <fieldset> + <legend> groups all options. Legend serves as the group label for screen readers.
2
Radio input
Native input[type=radio]. accent-color:#6366F1. width/height:16px. Same name attribute on all inputs in the group.
3
Option label
13px fw-500. Wrapped in <label> for full-row click area.
4
Option sub-label (optional)
11px #94A3B8. Describes the option in more detail.
Variants
Vertical (default)
With sub-labels
States
Unselected
Empty circle
Selected
Filled with accent-color:#6366F1
Disabled
opacity:.5, cursor:not-allowed
Properties
| Property | Type | Required | Default | Description |
|---|---|---|---|---|
| name | string | required | — | All radio inputs in a group share the same name. This makes them mutually exclusive. |
| value | string | required | — | Each option has a unique value submitted on form select. |
| defaultValue | string | optional | undefined | Pre-selected option value. |
| disabled | boolean | optional | false | Per-option or group-level disable. |
| legend | string | required | — | Group label in <legend> element. Can be visually hidden but must exist. |
Behavior
| Trigger | Behavior |
|---|---|
| Click option | Selects that option. Deselects all others in same name group. Fires onChange with new value. |
| Arrow keys | When focused, arrow keys cycle through options in the group. Native browser behavior. |
| Tab | Moves focus into/out of the radio group. Inside the group, arrow keys navigate. |
Accessibility
| Requirement | Implementation |
|---|---|
| Group semantics | Wrap all options in <fieldset> with <legend>. Legend can be visually hidden but must exist in DOM. |
| Native input | Always use input[type=radio]. Never divs or spans that simulate radio buttons. |
| Keyboard | Tab enters group. Arrow keys cycle options. Space selects focused option. |
| Label association | Wrap each input+label in <label> or use for/id pairing. |
Composition
Allowed
Inside form-group with form-label as legend
2–6 options maximum
Inside modal forms
Forbidden
More than 6 options — use Select
Without fieldset + legend wrapper
Mixed with Checkbox in same group
Best Practices
Do
Sub-labels help users understand the difference between options.
Don't
More than 6 options — use Select instead.
Content Rules
Good option label
Monthly / Annual / Lifetime
Short, noun-based, parallel structure.
Bad option label
I want to be billed monthly
First person, sentence-length. Options should be nouns.
AI Implementation Guide
For AI coding assistants: Always use native input[type=radio] elements. All options in a group MUST share the same name attribute — this is what makes them mutually exclusive. Wrap the entire group in <fieldset> + <legend>. Each option is a <label> wrapping input + text. accent-color:#6366F1 for brand color. Max 6 options — beyond that, switch to Select component.
Related Components
Design Decisions
Why limit to 6 options maximum?
Radio groups work because users can scan all options at once for comparison. Beyond 6 options, scanning becomes tedious and a Select dropdown (which hides options until needed) is more efficient. The threshold of 6 is a widely-accepted UX heuristic.
Changelog
v1.0.0July 2026Added
- Initial release — vertical layout, with/without sub-labels, disabled state
- Native input[type=radio] with accent-color:#6366F1
- fieldset + legend for accessibility