Skip to content

Radio Group

Stable

Lets people choose exactly one option from a small set, with every option visible at once.

Installation

$ pnpm dlx shadcn@latest add https://www.prfct.dev/r/radio-group.json

Usage

import { Field, FieldLabel } from "@/components/ui/field"
import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group"
<RadioGroup defaultValue="daily">
  <Field orientation="horizontal">
    <RadioGroupItem value="daily" id="daily" />
    <FieldLabel htmlFor="daily">Daily summary</FieldLabel>
  </Field>
  <Field orientation="horizontal">
    <RadioGroupItem value="weekly" id="weekly" />
    <FieldLabel htmlFor="weekly">Weekly summary</FieldLabel>
  </Field>
</RadioGroup>

The selected radio fills with the brand color and its dot springs into place.

Examples

With descriptions

When options need explaining, pair each label with a description in FieldContent. People compare options by reading the descriptions side by side — one of the main reasons to prefer radios over a select.

Choice cards

Wrap each field in a FieldLabel to make the whole card clickable. Cards suit decisions with a price, a limit or a feature list — plans, shipping speeds, deployment targets.

Horizontal

Lay short options out in a row when they read as a scale or a set of peers. Use FieldSet and FieldLegend to name the group; a row of radios without a question is ambiguous.

Table density

States

Disable a group when the choice doesn't apply yet, and explain why nearby. For validation, set required, mark the items aria-invalid and show a FieldError under the group.

Billing cycle
Shipping speed

Guidelines

When to use

  • To choose exactly one option from two to about seven.
  • When people benefit from seeing and comparing every option at once.

When not to use

  • To select several options — use Checkboxes.
  • For a single on/off setting — use a Switch or a checkbox.
  • For more than about seven options, or when space is tight — use a Select.
  • For compact segmented choices in toolbars (view modes, alignment) — use a Toggle Group.

Defaults

Preselect the most common or safest option — a radio group can't be returned to "nothing selected" once people choose, so an empty group only makes sense when the choice must be deliberate. In that case, validate it.

Standard — free

Express — $12

Do.A sensible default; people change it only if they need to.

Subscribe to the newsletter

Don’t.A single radio can never be unselected — use a checkbox instead.

Order

Order options logically — by magnitude, time, or likelihood — and keep the list vertical unless the options are very short. Align radios on the left so the labels form a clean, scannable column.

Accessibility

RadioGroup renders role="radiogroup" and each item role="radio" with aria-checked. The group behaves as a single tab stop with roving focus, following the ARIA radio group pattern.

KeyBehavior
Tab
Moves focus into the group — to the checked radio, or the first one if none is checked — and out of it.
Moves to and checks the next radio, wrapping at the end.
Moves to and checks the previous radio, wrapping at the start.
Space
Checks the focused radio if it isn't checked yet.
  • Name the group. Use FieldSet + FieldLegend, or aria-label / aria-labelledby on RadioGroup, so the question is announced along with each option.
  • Label every radio with a FieldLabel that points at its id. Base UI links the label to the visible radio, so clicking the text selects it.
  • Boundaries and targets. Radios use the input token for their border (3:1, WCAG 1.4.11) and a 24×24px hit area around the 16px circle.

API reference

RadioGroup

Renders a <div role="radiogroup">. Accepts every prop of Base UI's RadioGroup.

PropTypeDefault
value

The selected value. Use with onValueChange when controlled.

ValueNo default
defaultValue

The initially selected value when uncontrolled.

ValueNo default
onValueChange

Called when the selection changes.

(value, details) => voidNo default
name

Submits the selected value with a form.

stringNo default
required

Requires a selection before submitting.

booleanfalse
disabled

Disables every radio in the group.

booleanfalse
readOnly

Shows the selection but prevents changing it.

booleanfalse

RadioGroupItem

Renders a <span role="radio"> with a hidden input. Accepts every prop of Base UI's Radio.Root.

PropTypeDefault
valuerequired

The value this radio represents.

ValueNo default
disabled

Disables this radio only.

booleanfalse
id

Lets a FieldLabel target the radio with htmlFor.

stringNo default
aria-invalid

Shows the error state.

booleanNo default