Skip to content

RadioGroup

Terminal window
$ npx shadcn@latest add https://lacodda.github.io/dowel/r/radio-group.json
See it liveA column of options, a row of them, and a disabled group.→

Reach for this when the options are worth the space. A handful of short choices read faster laid out than hidden behind a trigger, and each one becomes a target rather than a step. Past about five, or when the labels are long, a Select is the honest choice — this is not a Select with more pixels.

<RadioGroup aria-label="Ripeness" defaultValue="ripe">
<Radio value="green">Green</Radio>
<Radio value="ripe">Ripe</Radio>
<Radio value="soft">Soft</Radio>
</RadioGroup>

The group is the control. That is what the arrow keys move within, what a screen reader announces as one thing with a position in it, and why the group takes the value rather than each button. Radio outside a group is a checkbox that cannot be unchecked, which is why it is only useful inside one.

One tab stop, not three. Tab reaches the group and the arrows move the choice — the behaviour a native radio group has and a row of styled buttons does not.

orientation="horizontal" for two or three short options. A column is the default because it stays readable as labels grow.

Name the group. It is the question the options answer, and without it a reader hears three values and no subject:

<RadioGroup aria-label="Ripeness"> {/* or */}
<Field label="Ripeness"><RadioGroup>... {/* named by the field */}

Props

Read from the types in ui/radio-group.tsx, the file a product copies - so the description of each prop is also what an editor shows over it there.

RadioGroup

PropTypeDefault
childrenrequiredReactNode
valuestringThe value of the selected radio. Controlled; pair it with onValueChange.
defaultValuestringThe value selected at first, when the group is uncontrolled.
onValueChange(value: string) => voidCalled with the value of the radio the reader chose.
disabledbooleanDisables every radio in the group.
readOnlybooleanShows the selection but does not let it change.
requiredbooleanMarks the group as requiring a choice for form validation.
namestringThe field name submitted with a form.
orientationhorizontal | vertical | nullLay the options out in a row. For two or three short ones; a column is the default because it stays readable as labels grow.
aria-labelstringThe accessible name of the group, when no visible label names it.
classNamestring

Radio

PropTypeDefault
valuerequiredstringWhat the group's value becomes when this radio is chosen.
childrenReactNodeThe words next to the dot.
disabledbooleanDisables this radio alone; the label dims with it.
classNamestring

Accessibility

The examples on the stand, through axe 4.14.0 in a browser, in both themes, against WCAG 2.2 A and AA and axe's best practices: 18 rules applied and passed, and none failed. The accessibility report has every item.

Left to a person, where axe could not decide: aria-toggle-field-name, duplicate-id-aria.

History

Each release that changed ui/radio-group.tsx - the file a product copies - newest first.

  1. v0.41.0
    • docs read every props table from the component's types ee3b159
  2. v0.16.0
    • feat a field, and the three ways of choosing 7df746d