Skip to main content

Design system components

RadioGroup

Accessible radio button group with legend and validation; with startLabel and endLabel it is a rating scale.

Status: beta. Group: form. Markdown version: /design-system/components/radio-group.md

When to use

RadioGroup is the standard way to ask for an exclusive choice: it renders a fieldset legend, the labelled radios, helper and error text, and manages the selection in controlled or uncontrolled mode.

When not to use

  • Do not use radios for actions or navigation; picking an option must not immediately commit anything.

Look-alikes

  • CheckboxGroup: Do not use it for exclusive choices; that is RadioGroup.
  • Select: Use Select for five or more exclusive options, or when space is tight; RadioGroup is better when all options should stay visible.
  • SelectableCard: For bare text options without supporting content, use RadioGroup or CheckboxGroup.
  • SelectableCardGroup: Do not use rich cards when plain RadioGroup or CheckboxGroup labels communicate the choices clearly.

Props

RadioGroup props
PropTypeDefaultDescriptionRequired
namestringnoneNative form field name shared by the set; auto-generated when omitted.No
legendstringnoneGroup label rendered as the fieldset legend.Yes
optionsRadioGroupOption[]noneRadio options; per-option disabled keeps the choice visible.Yes
valuestringnoneControlled selected value; "" is treated as absent (uncontrolled)No
defaultValuestringnoneInitial value when uncontrolled.No
onValueChange(value: string) => voidnoneFired with the next value when selection changes.No
orientation"horizontal" | "vertical"verticalStack direction.No
size"sm" | "md" | "lg" | "S" | "M" | "L"mdRadio control size.No
disabledbooleanfalseDisables the whole set.No
errorstringnoneError message; announces via role=alert and sets aria-invalid.No
helperTextstringnoneHelper copy below the group; always rendered, alongside error when both are set.No
startLabelstringnoneAnchor shown before the first option, for rating scales ("Serious" in Serious 1 to 5 Playful). Announced paired with its option, not on its own.No
endLabelstringnoneAnchor shown after the last option; pairs with startLabel.No
hideLegendbooleanfalseKeeps the legend as the accessible name but hides it visually.No
classNamestringnoneMerged onto the fieldset.No

Variants

  • Available orientations: vertical, horizontal (default vertical). Forwarded to fieldset layout class in RadioGroup.module.css.
  • Available sizes: sm, md, lg, S, M, L (default sm).

Invalid combinations

  • MUST NOT: value and defaultValue set together. value makes the component controlled and defaultValue uncontrolled; pass one, not both.

Keyboard

The contract records no keyboard interaction.

Rules

Every item under When not to use is a MUST NOT. MUST and SHOULD follow RFC 2119.

RadioGroup rules
LevelRuleHow it is checked
MUST NOTvalue and defaultValue set together. value makes the component controlled and defaultValue uncontrolled; pass one, not both.Checked by the MCP tool validate_component_usage.
MUSTRequired stories produce no axe violations at the configured severity.Automated by npm run test:stories:matrix:ci. WCAG 2.5.8.
MUSTThe accessibility tree (role, name, state) matches the committed snapshot for every required story.Automated by npm run test:stories:matrix:ci. WCAG 1.3.1, 4.1.2.
MUSTThe component remains legible and operable under a real browser forced-colors: active pass.Automated by npm run test:stories:hc.
MUSTA human completed an end-to-end accessibility review of this component.Manual review, last on 2026-05-28.
SHOULDWrite the legend as the question (Delivery speed); the options then read as answers.Not stated in the contract.
SHOULDUse it whenever all options should be visible at once; switch to Select when space is tight or options exceed about seven.Not stated in the contract.
SHOULDPreselect the safest common option with defaultValue when a recommendation exists.Not stated in the contract.
SHOULDUse orientation=horizontal only for a few short options that still fit one line on mobile.Not stated in the contract.
SHOULDFor a rating scale, give numbered options with startLabel and endLabel (Serious 1 to 5 Playful) and hideLegend when the anchors already say what is rated; the legend stays the accessible name.Not stated in the contract.
SHOULD NOTDo not leave a required group unselected without a recovery plan; users cannot un-pick a radio once one is chosen.Not stated in the contract.
MUST NOTMaintainers: Do not bypass design tokens or skip forced-colors verification at beta.Release review; not machine-checked.

Install and import

  • Install: npm install @digitaltableteur/react (version 0.9.1, restricted access on npm).
  • Import: import { RadioGroup } from "@digitaltableteur/react";
  • Entry point: @digitaltableteur/react/forms exports it too.
  • Styles: import @digitaltableteur/react/style.css once at the app boundary.
  • Also available as the custom element <dt-radio-group>; see the custom elements manifest.