RadioGroup
$ npx shadcn@latest add https://lacodda.github.io/dowel/r/radio-group.jsonReach 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 */}RadioGroup
Section titled “RadioGroup”| Prop | Type | Default | |
|---|---|---|---|
value |
string |
Controlled | |
defaultValue |
string |
Uncontrolled | |
onValueChange |
(value) => void |
||
orientation |
vertical | horizontal |
vertical |
|
disabled, readOnly, required |
boolean |
false |
|
name |
string |
For a form |
| Prop | Type | Default | |
|---|---|---|---|
value |
string |
Required | |
children |
ReactNode |
The words next to the dot | |
disabled |
boolean |
false |