@ai-created/ui
All components

Fields & selection

RadioGroup

A controlled fieldset for selecting exactly one value from a small, visible option set.

RadioGroupRadioGroupPropsRadioOption
View source

Component workbench

Configure the production component, inspect it at responsive widths, copy synchronized JSX, and share the exact state from one workspace.

Team discipline

Anatomy

Named regions define what belongs to the component, what remains optional, and where semantic responsibility lives.

1

Fieldset

Required

Semantic group and disabled boundary.

fieldset
2

Legend

Required

Persistent group name.

legend
3

Native radio

Required

Visually hidden option input.

input[type=radio]
4

Indicator

Required

16px circular selection mark.

5

Option label

Required

Visible name and 44px minimum row target.

label

Construction and authoring

The Figma-equivalent asset model, auto-layout, resizing, properties, slots, content bounds, localization, and governance contract.

Asset kind

component

Design library name

Components/Forms/Radio group

Maturity

stable

Last reviewed

2026-08-29

Canvas applicability

Publish vertical and horizontal group variants with nested option instances.

Auto layout

Direction
vertical
Gap
12px between legend and options; 12px options vertically or 24px horizontally
Padding
0px
Alignment
Start
Wrap
Horizontal options may wrap

Resizing

Width
fill
Height
hug
Minimum width
200px
Maximum width
Parent controlled
Minimum height
Content controlled
Maximum height
Content controlled
Overflow
visible

Exposed design properties

PropertyTypeDefaultCode mappingOptions or notes
Orientationvariantverticalorientationvertical, horizontal
Selected valueRequiredvariantNonevalueNo additional constraint
DisabledbooleanfalsedisabledNo additional constraint
LegendRequiredtextChoose onelegendNo additional constraint
OptionsRequiredslotNoneoptionsNo additional constraint

Nested assets and slots

Fieldset

primitive / required

Semantic group boundary.

<fieldset>

Legend

subcomponent / required

Group question or name.

<legend>

Radio option

subcomponent / required

Repeatable native radio, indicator, and label.

RadioOption data item

Content limits

Options

Recommended two to seven choices

Overflow: Use Dropdown or a searchable picker for larger sets.

All choices should be comparable without excessive scanning.

Option label

One line preferred, maximum two lines

Overflow: Wrap and align indicator with the first line.

Peer choices need parallel, concise wording.

Localization and RTL

Translatable: Legend, Option labels

  • Options flow from logical start; horizontal arrow behavior follows browser radio semantics.
  • Selection indicator does not mirror.
  • Test the longest option in horizontal layout.
  • Test mixed enabled and disabled options.

Responsive behavior

Vertical is the safe default.

Parent-selected narrow breakpoint

  • Change horizontal groups to vertical before labels collide.
  • Do not change option order between widths.

Authoring limits

  • Figma variants cannot reproduce native arrow-key selection.
  • Values are stable domain keys and must not be translated even when labels are.

Accountable owner

Design systems form foundations owner

Canonical source: src/components/RadioGroup.tsx

  • Orientation or option behavior changes require keyboard-navigation review.
  • A breaking property, token, or behavior change requires design and engineering approval, a migration note, and a major release.
  • The design asset, implementation, documentation, accessibility contract, and regression coverage must ship in the same change.
Read the system construction standard

Visual specification

These measurements and semantic tokens define the supported visual contract. Local overrides should preserve the same hierarchy and interaction cues.

Option row minimum height

44px

Indicator

16 × 16px

Selected dot

9.6 × 9.6px

Indicator/label gap

10px

Vertical option gap

10px

Horizontal option gap

16px

Rules

  • Show all choices when the set is short enough.
  • Use vertical orientation when labels vary in length.
  • Stable values belong in domain data; labels may change.

Token dependencies

--color-action-primary

Selected indicator.

--color-on-action

Selected inner mark.

--color-control-border / --color-control-border-strong

Unselected and hover boundary.

--color-focus

Peer focus outline.

--color-text2

Legend and option labels.

States and behavior

A component is not complete until its passive, interactive, disabled, and exceptional states remain understandable in both themes.

selected

Trigger
Option value equals group value.
Visual response
Solid action circle with white inner dot.
Behavior
This option is the group tab stop.
Accessibility
Native checked state is exposed.

unselected

Trigger
Option value differs.
Visual response
Transparent indicator with strong border.
Behavior
Activation selects this value.

disabled

Trigger
Group or option is disabled.
Visual response
50% opacity and not-allowed cursor.
Behavior
Option cannot receive focus or selection.

focus-visible

Trigger
Keyboard focus reaches a radio.
Visual response
2px focus outline with 3px offset on indicator.
Behavior
Native radio navigation remains active.

Accessibility contract

Semantics, accessible naming, keyboard behavior, focus and announcements are implementation requirements, not optional documentation.

Semantics
Native fieldset, legend, and radio inputs; an additional radiogroup wrapper carries aria-label.
Accessible name
The required legend names the group; each visible option label names its radio.
  • Provide at least two meaningful options.
  • Do not duplicate option values.
  • Disabled options must remain understandable in context.
  • Keep name stable when integrating with native form submission.

Keyboard behavior

Arrow keys
Moves selection and focus among enabled native radios.
Space
Selects the focused option.
Tab
Enters or leaves the radio group as one stop.

Implementation

Use the public package API and preserve the controlled-state, native-attribute, and ref contracts described below.

tsx
import { RadioGroup, type RadioOption } from '@ai-created/ui';

Server Component compatible

  • Generic string values preserve a narrow domain union.
  • The fieldset ref is forwarded.
  • onChange receives the chosen value directly.
tsx
<RadioGroup options={options} value={size} onChange={setSize} legend="Size" />

Public API

These props and helpers are compatibility contracts. Changes require migration guidance and release notes.

PropTypeDefaultContract
optionsRadioOption<T>[]requiredOptions with value, label, and optional disabled.
valueTrequiredControlled selected value.
onChange(value: T) => voidrequiredCalled when selection changes.
legendstringrequiredFieldset legend.
namestringgenerated idNative radio group name.
disabledbooleanfalseDisables the group.
orientationhorizontal | verticalverticalOption layout.

Usage guidance

These rules keep the component recognizable across products without preventing deliberate composition.

Do

  • Use for mutually exclusive peer choices.
  • Order choices predictably and keep labels parallel.

Do not

  • Do not use for independent booleans.
  • Do not use for very large or searchable datasets.

Testing contract

The component should be verified as rendered UI, an interaction model, an accessibility surface, and a theme-aware visual artifact.

Unit

  • Renders options, generated ids/name, orientation, and disabled merging.
  • Calls onChange with the activated value.

Interaction

  • Pointer, Space, and arrow behavior select enabled options only.

Accessibility

  • Fieldset/legend/input/label relationships and group name are valid.

Visual

  • Capture orientations, selection, focus, group disabled, option disabled, and both themes.

Related specifications