Radio

Single-choice selection controls for mutually exclusive options. Users can select exactly one option from a set. Uses convex physics with the selected indicator animating in with a spring effect. Use radio buttons when only one selection is allowed.

Radio States
Default
Error
Disabled
Unselected
Selected

Physics Radio buttons use convex shadows for depth. On hover, the button elevates slightly (-1px). The inner dot scales in with spring easing when selected.

Size Variants
Small (16px)
Medium (20px)
Large (24px)
Selected: md
Hover
Radio lifts -1px with elevated shadow
Select
Inner dot scales in with spring easing
Mutual Exclusion
Previous selection automatically deselects

Examples

Basic RadioGroup

Use RadioGroup with options array for simple single-choice selection.

Select a plan
JSX
<RadioGroup
  name="plan"
  label="Select a plan"
  options={[
    { value: 'free', label: 'Free' },
    { value: 'pro', label: 'Pro' },
    { value: 'enterprise', label: 'Enterprise' },
  ]}
  value={selectedPlan}
  onChange={setSelectedPlan}
/>

With Descriptions

Add secondary text to help users understand each option.

Choose your plan
JSX
<RadioGroup
  name="pricing"
  label="Choose your plan"
  options={[
    { value: 'starter', label: 'Starter', description: 'Best for personal projects - $0/month' },
    { value: 'team', label: 'Team', description: 'For small teams up to 10 - $29/month' },
    { value: 'business', label: 'Business', description: 'Unlimited users - $99/month' },
  ]}
  defaultValue="team"
/>

Horizontal Layout

Arrange radio buttons horizontally for compact layouts.

Select size
JSX
<RadioGroup
  name="size-select"
  label="Select size"
  orientation="horizontal"
  options={[
    { value: 'xs', label: 'XS' },
    { value: 's', label: 'S' },
    { value: 'm', label: 'M' },
    { value: 'l', label: 'L' },
    { value: 'xl', label: 'XL' },
  ]}
  defaultValue="m"
/>

With Disabled Options

Disable specific options that are temporarily unavailable.

Shipping method
Express shipping is temporarily unavailable
JSX
<RadioGroup
  name="shipping"
  label="Shipping method"
  options={[
    { value: 'standard', label: 'Standard (5-7 days)' },
    { value: 'express', label: 'Express (2-3 days)', disabled: true },
    { value: 'overnight', label: 'Overnight' },
  ]}
  defaultValue="standard"
  helperText="Express shipping is temporarily unavailable"
/>

Required Field

Mark the group as required with a visual indicator.

Preferred contact method *
JSX
<RadioGroup
  name="contact-pref"
  label="Preferred contact method"
  required
  options={[
    { value: 'email', label: 'Email' },
    { value: 'phone', label: 'Phone' },
    { value: 'sms', label: 'SMS' },
  ]}
/>

Error State

Display validation errors when no option is selected.

Select an option *
Please select one of the options to continue
JSX
<RadioGroup
  name="required-select"
  label="Select an option"
  required
  status="error"
  helperText="Please select one of the options to continue"
  options={[
    { value: 'opt1', label: 'Option 1' },
    { value: 'opt2', label: 'Option 2' },
    { value: 'opt3', label: 'Option 3' },
  ]}
/>

Success State

Confirm successful selection with a success status.

Delivery time
JSX
<RadioGroup
  name="confirmed"
  label="Delivery time"
  status="success"
  options={[
    { value: 'morning', label: 'Morning (8am - 12pm)' },
    { value: 'afternoon', label: 'Afternoon (12pm - 5pm)' },
    { value: 'evening', label: 'Evening (5pm - 9pm)' },
  ]}
  defaultValue="afternoon"
/>

All Sizes Comparison

Compare all three sizes for different density requirements.

Small size
Medium size (default)
Large size
JSX
<RadioGroup name="small" label="Small" size="sm" ... />
<RadioGroup name="medium" label="Medium" size="md" ... />
<RadioGroup name="large" label="Large" size="lg" ... />

Disabled Group

Disable the entire group when the section is not applicable.

Account type (locked)
JSX
<RadioGroup
  name="disabled-group"
  label="Account type (locked)"
  disabled
  options={[
    { value: 'personal', label: 'Personal' },
    { value: 'business', label: 'Business' },
  ]}
  defaultValue="personal"
/>

Payment Method Pattern

Common pattern for payment method selection with descriptions.

Payment method
JSX
<RadioGroup
  name="payment"
  label="Payment method"
  options={[
    { value: 'card', label: 'Credit or debit card', description: 'Visa, Mastercard, Amex accepted' },
    { value: 'paypal', label: 'PayPal', description: 'Pay securely with your PayPal account' },
    { value: 'bank', label: 'Bank transfer', description: 'Direct deposit (2-3 business days)' },
  ]}
  value={paymentMethod}
  onChange={setPaymentMethod}
/>

Standalone Radio

Use individual Radio components for custom layouts.

JSX
<Radio name="standalone" value="yes" label="Yes, I agree" />
<Radio name="standalone" value="no" label="No, I disagree" />
<Radio name="standalone" value="maybe" label="I need more information" />

With Helper Text

Add group-level helper text for additional context.

Email frequency
You can change this setting anytime in your account preferences
JSX
<RadioGroup
  name="frequency"
  label="Email frequency"
  helperText="You can change this setting anytime in your account preferences"
  options={[
    { value: 'daily', label: 'Daily digest' },
    { value: 'weekly', label: 'Weekly summary' },
    { value: 'monthly', label: 'Monthly newsletter' },
  ]}
  defaultValue="weekly"
/>

Best Practices

Do

  • Use for mutually exclusive options
  • Provide a default selection when possible
  • Keep option labels concise
  • Use descriptions for complex choices
  • Group related options together

Don't

  • Don't use for multi-select (use Checkbox instead)
  • Don't use more than 7 options (consider Select)
  • Don't leave without a default if one is required
  • Don't mix radio buttons with checkboxes in the same group

RadioGroup Props

PropTypeDefaultDescription
namestringrequiredForm field name (required for radio groups)
valueT-Controlled selected value
defaultValueT-Initial selected value (uncontrolled)
onChange(value: T) => void-Callback when selection changes
optionsRadioGroupOption[]-Array of options with value, label, description
orientation'horizontal' | 'vertical''vertical'Layout direction
size'sm' | 'md' | 'lg''md'Radio button size
labelstring-Group label
helperTextstring-Helper text below group
status'default' | 'success' | 'error''default'Validation status
requiredbooleanfalseMark as required
disabledbooleanfalseDisable entire group

Accessibility

  • Keyboard: Arrow keys to navigate between options, Space/Enter to select
  • ARIA: Uses role="radiogroup" with aria-required
  • Focus: Tab moves to group, arrows move within group
  • Grouping: Always use RadioGroup for proper accessibility
  • Name: All radios in a group must share the same name attribute