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.
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.
Examples
Basic RadioGroup
Use RadioGroup with options array for simple single-choice selection.
<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.
<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.
<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.
<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.
<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.
<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.
<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.
<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.
<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.
<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.
<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.
<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
| Prop | Type | Default | Description |
|---|---|---|---|
name | string | required | Form field name (required for radio groups) |
value | T | - | Controlled selected value |
defaultValue | T | - | Initial selected value (uncontrolled) |
onChange | (value: T) => void | - | Callback when selection changes |
options | RadioGroupOption[] | - | Array of options with value, label, description |
orientation | 'horizontal' | 'vertical' | 'vertical' | Layout direction |
size | 'sm' | 'md' | 'lg' | 'md' | Radio button size |
label | string | - | Group label |
helperText | string | - | Helper text below group |
status | 'default' | 'success' | 'error' | 'default' | Validation status |
required | boolean | false | Mark as required |
disabled | boolean | false | Disable entire group |
Accessibility
- Keyboard: Arrow keys to navigate between options, Space/Enter to select
- ARIA: Uses
role="radiogroup"witharia-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