Skip to content

RadioGroup ​

One choice from a few options that people should see side by side.

Open in Storybook to try every prop.

When to use ​

  • Two to five options, when seeing them all helps the choice, e.g. "Mark as leavers" / "Keep on roll".

When not to use ​

  • More than five options, or a minor choice: use Select.
  • A yes / no question: use Checkbox (in a form) or Switch (a setting).

Anatomy ​

PartRequiredNotes
labelYesThe question, above the options. The group's accessible name.
helperNoUnder the label, or behind a ? (InfoTip) beside it.
optionYesA 16px circle, its label and optional description. The chosen one has an 8px primary dot.
messageNoError text under the options.

Properties ​

PropertyTypeDefaultDescription
modelValuestring | number—The chosen option's value; undefined until one is chosen.
labelstring—Required.
options{ label, value, description?, disabled? }[]—Required.
helperstring—
helperPlacementbelow | iconbelowAs on every field.
errorTextstring—
namestring—For native form submission.
required / disabledbooleanfalse

Options always stack vertically: no horizontal layout, so labels and descriptions never crowd.

States ​

StateAppearanceNotes
Not chosenWhite circle, black 55% border.
HoveredBlack border.Web / desktop only.
ChosenPrimary border and dot.
Focused2px focus ring, 2px out.Keyboard only.
ErrorRed borders, red message with icon.
Disabled40% opacity: the whole group, or one option.

Spacing and layout ​

  • Label to helper: 2px. Label block to options: 6px. Options: 8px apart. Circle to option label: 8px.

Behaviour ​

  • Tab moves into the group (to the chosen option, or the first) and out again; the arrow keys move and choose.
  • The whole row is pressable: the circle, its label and its description. The description is not part of the accessible name; it stays the description.
  • Once chosen, an option can't be unchosen: start with nothing chosen if "none" isn't a valid answer, or add a "None" option.

Accessibility ​

  • role="radiogroup" named by the label (aria-labelledby), described by helper and error; aria-invalid on error.
  • Each option is role="radio", named by its <label>, described by its description.

Platform adaptation ​

PlatformImplementationDifferences
Web / desktop (Vue)RadioGroup.vueReka UI RadioGroup.
iOS (SwiftUI)—Picker with .inline style in a Form.
Android (Compose)—RadioButton rows with Modifier.selectableGroup().

Tokens used ​

TokenUsed for
color-primaryChosen border and dot
color-redError
color-focusFocus ring

Do / Don't ​

DoDon't
Keep option labels short, with detail in description.Put a paragraph in the label.
Order options logically (most common first, or a natural order).Order them at random.

Released under the PolyForm Noncommercial License 1.0.0.