Radio group

Picks one of a few choices.

Checked

  • falsedefault

  • true

States

  • rest

  • hover

  • held

  • focus-visible

  • chosen

  • invalid

  • disabled

Usage

When to use it
Use
Exactly one of two to six choices, each needing a line about its consequence.
Use
A form setting saved with the form, where the person should compare before choosing.
Not for
Two to five views of the same thing, switched at once. Use Segmented control.
Not for
Any number can be on. Use Checkbox.
Not for
A single on or off that applies at once. Use Switch.

Rules

6 rules
Must
Use RadioGroupOption for each choice so its label and description share one target and are read together. Because a loose RadioGroupItem with text beside it has no name, and only the 16px circle takes the press.
Must
Name the group with a FieldLegend in a FieldSet, or aria-label. Because arrowing into an unnamed group, a screen reader announces the options with no question.
Must
Give the group a value or defaultValue unless choosing nothing is a real answer. Because a radio cannot be cleared once chosen, so an empty start the person must fix looks like a missing default.
Never
Colour the chosen radio or swap its small glaze for a flat fill. Because small glaze (glaze-sm) is how Glaze shows a chosen small control, and colour means status.
Should
Say why a disabled option is out of reach in its description.
Should
Keep a group to about six options; past that, use a select. Because a long column of circles pushes the rest of the form down and is slow to compare.

State order

7 states, highest first
1
disabled
2
invalid
3
chosen
4
held
5
focus-visible
6
hover
7
rest

Accessibility

4 checks
role="radiogroup" with one tab stop; each radio is named by its label and described by its consequence.
The open circle is --line-strong, 3.3:1 on paper; the chosen one is small glaze with a white dot (9.5:1 at the centre), so it reads without colour.
Each circle is 16px with a 28px hit area, and the whole option row is the target.
Focus is the 2px ink ring on the circle.

Keyboard

3 keys
Arrow keys
Move to the next or previous option and choose it, wrapping at the ends.
Space
Chooses the focused option.
Tab
Enters on the chosen option and leaves the group.

Edge cases

6 edge cases
Long description
Wraps under the label; the circle stays on the first line.
Nothing chosen
Tab lands on the first enabled option.
Disabled option
Arrow keys skip it; its text turns the disabled colour.
Right to left
The circle moves to the start with the label, and the arrows follow the reading order.
Dark theme
The chosen circle turns light glaze with a dark dot.
Forced colors
The chosen circle takes Highlight with a HighlightText dot.

API

5 props
value, defaultValue, onValueChange
Base UI RadioGroup
aria-invalid
boolean default false
disabled, readOnly, required, name
Base UI
RadioGroupOption label, description
ReactNode
RadioGroupItem value
string

Tokens

18 tokens
--paper
#ffffff
--field
#efefef
--pressed
rgb(5 5 5 / 0.10)
--line-strong
rgb(5 5 5 / 0.45)
--line-faint
rgb(5 5 5 / 0.06)
--text-1
rgb(5 5 5 / 0.80)
--text-2
rgb(5 5 5 / 0.60)
--fail
#e35e49
--glaze-sm-top
#6b6b6b
--glaze-sm-mid
#3d3d3d
--glaze-sm-bottom
#232323
--glaze-sm-highlight
rgb(255 255 255 / 0.30)
--glaze-sm-rim
rgb(0 0 0 / 0.55)
--glaze-sm-text
rgb(255 255 255 / 0.92)
--radius-pill
999px
--type-label
500 13px/1.35 var(--font-sans)
--type-body-sm
400 13px/1.5 var(--font-sans)
--focus
rgb(5 5 5 / 0.80)

Install

For your coding agent

GitHub

Please star me pookie

141

A new design system every week

Leave your email before you copy the prompt.