ComponentsFormRadio

Radio

6 colors · 3 sizes · card · button · segmented display modes

StatesColorsSizesHorizontalError stateCardButtonSegmented

Overview

6 colors · 3 sizes · card · button · segmented display modes

Default radio group

Live preview

Use radio buttons when someone must choose exactly one option from a visible set.

Notification preference
App.tsx
tsx
const [notify, setNotify] = useState('email')
 
<RadioGroup legend="Notification preference" value={notify} onChange={setNotify}>
<Radio value="email" label="Email" helperText="Receive updates via email" />
<Radio value="sms" label="SMS" helperText="Receive updates via text message" />
<Radio value="push" label="Push" helperText="Receive push notifications" />
<Radio value="none" label="None" helperText="Do not receive notifications" disabled />
</RadioGroup>

Show the complete choice set when comparison helps. Use Select when the list is long or space is constrained, and Checkbox when multiple choices are allowed.

Provide a sensible default only when it is safe and does not imply consent.

Anatomy

  • Root container and spacing boundary.
  • Primary content and optional secondary metadata.
  • State indicators and utility affordances (icons, badges, controls).
  • Optional helper text, grouping, and behavioral wrappers.

When to use

  • Choose Radio when a repeated, structured interaction is required.
  • Use it for clear, consistent operations across similar surfaces.
  • Use in forms, lists, and action workflows where clarity matters.

When not to use

  • Do not use only for decorative layout without interaction meaning.
  • Avoid duplicating the same behavior without distinct user context.
  • Prefer simpler HTML or textual content for static, non-interactive labels.

Variants

Component variants should be documented by API props and examples below.

States

Common states include idle, active, disabled, focused, and loading/pending states where applicable.

Behavior

Behavior should remain deterministic and keyboard-friendly, with clear visual feedback for every state transition.

Accessibility

  • Use semantic structure and visible labels whenever possible.
  • Preserve keyboard navigation and focus visibility.
  • Announce status and changes when context requires it.

Content guidelines

  • Prefer short, clear labels.
  • Keep content actions scannable and outcome-oriented.
  • Use consistent wording across similar components.

Examples

Default

Live preview

Vertical list with helper text and a disabled option

Notification preference
App.tsx
tsx
const [notify, setNotify] = useState('email')
 
<RadioGroup legend="Notification preference" value={notify} onChange={setNotify}>
<Radio value="email" label="Email" helperText="Receive updates via email" />
<Radio value="sms" label="SMS" helperText="Receive updates via text message" />
<Radio value="push" label="Push" helperText="Receive push notifications" />
<Radio value="none" label="None" helperText="Do not receive notifications" disabled />
</RadioGroup>

Colors

Live preview

Six color variants — default, secondary, success, warning, error, and info

Select color
App.tsx
tsx
const [color, setColor] = useState('default')
 
<RadioGroup legend="Select color" value={color} onChange={setColor} direction="horizontal">
<Radio value="default" label="Default" color="default" />
<Radio value="secondary" label="Secondary" color="secondary" />
<Radio value="success" label="Success" color="success" />
<Radio value="warning" label="Warning" color="warning" />
<Radio value="error" label="Error" color="error" />
<Radio value="info" label="Info" color="info" />
</RadioGroup>

Sizes

Live preview

sm, md (default), and lg radio sizes

Size
App.tsx
tsx
const [size, setSize] = useState('md')
 
<RadioGroup legend="Size" value={size} onChange={setSize}>
<Radio value="sm" label="Small" size="sm" />
<Radio value="md" label="Medium (default)" size="md" />
<Radio value="lg" label="Large" size="lg" />
</RadioGroup>

Horizontal layout

Live preview

Use orientation=horizontal for inline radio groups

Calendar view
App.tsx
tsx
const [view, setView] = useState('week')
 
<RadioGroup legend="Calendar view" value={view} onChange={setView} direction="horizontal">
<Radio value="day" label="Day" />
<Radio value="week" label="Week" />
<Radio value="month" label="Month" />
<Radio value="year" label="Year" />
</RadioGroup>

Error state

Live preview

Group-level error with message — requires a selection

Gender

Please select a gender

App.tsx
tsx
const [gender, setGender] = useState('')
 
<RadioGroup
legend="Gender"
value={gender}
onChange={setGender}
error={!gender}
errorText="Please select a gender"
>
<Radio value="male" label="Male" required />
<Radio value="female" label="Female" />
<Radio value="other" label="Other" />
</RadioGroup>

Card style

Live preview

Bordered card layout — ideal for plan or tier selection

Choose a plan
App.tsx
tsx
const [plan, setPlan] = useState('pro')
 
<RadioGroup legend="Choose a plan" value={plan} onChange={setPlan} display="card">
<Radio
value="starter"
label="Starter"
description="$0/month · 3 projects · Community support"
/>
<Radio
value="pro"
label="Pro"
description="$12/month · Unlimited projects · Priority support"
/>
<Radio
value="team"
label="Team"
description="$49/month · Up to 10 members · Admin controls"
/>
<Radio
value="enterprise"
label="Enterprise"
description="Custom pricing · Unlimited members · SLA"
disabled
/>
</RadioGroup>

Button style

Live preview

Pill-button style group — great for toggles and billing cycles

Billing cycle
App.tsx
tsx
const [billing, setBilling] = useState('yearly')
 
<RadioGroup legend="Billing cycle" value={billing} onChange={setBilling} display="button">
<Radio value="monthly" label="Monthly" />
<Radio value="quarterly" label="Quarterly" />
<Radio value="yearly" label="Yearly" />
</RadioGroup>

Segmented control

Live preview

Compact connected button group — ideal for view switchers

Calendar view
App.tsx
tsx
const [view, setView] = useState('week')
 
<RadioGroup legend="Calendar view" value={view} onChange={setView} display="segmented">
<Radio value="day" label="Day" />
<Radio value="week" label="Week" />
<Radio value="month" label="Month" />
<Radio value="year" label="Year" />
</RadioGroup>

Radio props

RadioGroup props

Props / API

Api Props

Props

PropTypeDefaultDescription
labelReactNode—Label text shown next to the radio
helperTextstring—Helper text shown below the label
requiredbooleanfalseMarks as required — adds * to label
errorbooleanfalseError state — red border
errorTextstring—Error message shown when error=true
cardbooleanfalseWraps the radio in a bordered card
descriptionstring—Description inside the card (card=true only)
size'sm' | 'md' | 'lg''md'Size of the radio button
color'default' | 'secondary' | 'success' | 'warning' | 'error' | 'info''default'Color when selected
disabledbooleanfalseDisables the radio button
valuestring—Value used inside RadioGroup
checkedboolean—Controlled checked state
defaultCheckedbooleanfalseUncontrolled initial checked state
onChangeReact.ChangeEventHandler<HTMLInputElement>—Change event callback
legendstring—Group label shown above the radios
valuestring—Controlled selected value
onChange(value: string) => void—Callback fired when selection changes
display'default' | 'card' | 'button' | 'segmented''default'Layout style for the group
color'default' | 'secondary' | 'success' | 'warning' | 'error' | 'info'—Color applied to all child radios
size'sm' | 'md' | 'lg'—Size applied to all child radios
orientation'horizontal' | 'vertical''vertical'Stacking direction of the radios
errorbooleanfalseError state for the group
errorTextstring—Error message shown below the group
childrenReactNode—Radio components with a value prop