Radio
Exclusive choice that stays on the page. RadioGroup.Root owns the value, the shared name, disabled, and invalid. RadioGroup.Item cannot take checked or name. An item outside a root throws.
The group type requires aria-label or aria-labelledby. A role="radiogroup" div is not a labelable control, so do not point Label htmlFor at the group. Caption it with Text and aria-labelledby.
value={null} is controlled with nothing selected. Omit value for uncontrolled.
const captionId = useId()
<Text as="span" id={captionId} size="s" weight="medium">Plan</Text>
<RadioGroup.Root aria-labelledby={captionId} value={plan} onValueChange={setPlan}>
<RadioGroup.Item value="free">Free</RadioGroup.Item>
<RadioGroup.Item value="pro">Pro</RadioGroup.Item>
</RadioGroup.Root>
Same-name native radios move focus with arrow keys. The group does not add a keyboard handler.
Use Radio when the options stay visible. Use OptionList when the options live in a popover or sheet. Wiring both to the same value is a QA fail.
When to use
When: Exclusive choice that stays visible on the page. Group owns value/name; caption via aria-label / aria-labelledby.
When not: Independent toggles → Checkbox. Overlay list → OptionList. Same value also wired to OptionList (dual-wire = fail).
Props
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
| aria-label | string | no | — | Accessible name when no visible caption exists. Exactly one of aria-label or aria-labelledby. |
| aria-labelledby | string | no | — | Id of the visible caption. Exactly one of aria-label or aria-labelledby. |
| value | string | null | no | — | Controlled value. null is controlled with nothing selected. Omit for uncontrolled. |
| defaultValue | string | null | no | — | Initial value when uncontrolled. |
| onValueChange | (value: string) => void | no | — | Fires with the next selected value. |
| name | string | no | — | Shared native name. Generated when omitted. |
| disabled | boolean | no | — | Disables every radio. |
| invalid | boolean | no | — | Marks every radio invalid. |
| orientation | "vertical" | "horizontal" | no | "vertical" | Layout and aria-orientation. |
| children | React.ReactNode | no | — | RadioGroup.Item children. |
| className | string | no | — | Optional class on the radiogroup. |
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
| value | string | yes | — | Option value. The group owns selection. |
| children | React.ReactNode | yes | — | Visible label. |
| disabled | boolean | no | — | Disables this option. The group disabled flag also applies. |
| className | string | no | — | Optional class on the wrapping label. |