Radio Group
A set of checkable buttons where only one can be selected at a time. Built for React applications with Next.js integration and TypeScript support.
You know those round buttons where you can only pick one option? Like choosing a shipping method or selecting a plan? That's radio groups - they make sure users can only pick one thing from a set of choices.
Select your preference
Classic radio group for single-choice selection:
Built on Radix UI RadioGroup with proper keyboard navigation and ARIA support. This free open source React component handles all the focus management and accessibility while looking exactly how you want it.
npx shadcn@latest add radio-group
When to use radio buttons
Radio buttons aren't just checkboxes that hate each other. They're for when you need exactly one choice:
- Mutually exclusive options - Only one can be true
- Always visible choices - All options shown upfront
- Small sets of options - Usually 2-7 choices max
- Important decisions - Users need to see all options
- Default selections - One option can be pre-selected
- Keyboard navigation - Arrow keys move between options
Useful radio group patterns
Settings and preferences
Common pattern for app settings:
Form with validation
Integrated with react-hook-form and validation:
Cards layout
Sometimes radio buttons work better as cards:
These patterns show up everywhere because they solve real problems. Settings that need one choice, form fields that need validation, survey questions that need a single answer.
Perfect for forms and settings
Works great anywhere users need to make a single choice from a visible set - checkout flows, settings panels, surveys, configuration wizards. The kind of decisions where seeing all options matters.
Drops right into Next.js projects. Full TypeScript support. Styled with Tailwind CSS to match the shadcn design system.
Built with Radix UI
Under the hood it's Radix UI RadioGroup, which handles the tricky stuff:
- Roving tabindex - One tab stop, then arrow keys
- Automatic IDs - Labels and inputs connected properly
- Group management - Only one selected at a time
- Orientation support - Vertical or horizontal layouts
- Loop navigation - Arrow keys wrap around
- Form integration - Works with native form submission
API Reference
RadioGroup
The root container that manages radio state.
Prop | Type | Default | Description |
---|---|---|---|
className | string | - | Additional CSS classes |
defaultValue | string | - | Default selected value for uncontrolled |
value | string | - | Controlled selected value |
onValueChange | (value: string) => void | - | Called when selection changes |
disabled | boolean | false | Disable all radio items |
name | string | - | Name for form submission |
required | boolean | false | Whether selection is required |
orientation | "horizontal" | "vertical" | "vertical" | Layout direction |
loop | boolean | true | Whether keyboard nav loops |
Data attributes:
[data-disabled]
: Present when disabled
RadioGroupItem
Individual radio button in the group.
Prop | Type | Default | Description |
---|---|---|---|
className | string | - | Additional CSS classes |
value | string | required | Value for this option |
id | string | - | ID for label association |
disabled | boolean | false | Disable this specific item |
Data attributes:
[data-state]
: "checked" | "unchecked"[data-disabled]
: Present when disabled
Keyboard Navigation
Key | Action |
---|---|
Tab | Focus the radio group |
Space | Select focused item |
Arrow Down | Move focus to next item |
Arrow Right | Move focus to next item |
Arrow Up | Move focus to previous item |
Arrow Left | Move focus to previous item |
Home | Focus first item |
End | Focus last item |
Form Integration
Works with react-hook-form and other form libraries:
<FormField
control={form.control}
name="option"
render={({ field }) => (
<RadioGroup
onValueChange={field.onChange}
defaultValue={field.value}
>
<RadioGroupItem value="option1" />
<RadioGroupItem value="option2" />
</RadioGroup>
)}
/>
Common Patterns
Pattern | Use Case | Implementation |
---|---|---|
Inline labels | Compact forms | Label next to radio |
Stacked labels | Mobile-friendly | Label below radio |
Card selection | Visual options | Radio inside card component |
Icon options | Visual choices | Icon + label + radio |
Description text | Complex options | Title + description per item |
Make radio groups that work
Few things to keep in mind:
- Always have a default - Don't make users think about the obvious choice
- Keep groups small - More than 7 options? Maybe use a select instead
- Labels that click - Make the whole label clickable, not just the circle
- Group related options - Visual spacing helps scanning
- Clear option names - "Yes/No" beats "Enable/Disable"
- Consider the layout - Vertical for most things, horizontal for short lists
- Show the selection - Make it super obvious what's selected
- Test keyboard navigation - Should feel natural with arrow keys
Progress
Displays an indicator showing the completion progress of a task. Built for React applications with Next.js integration and TypeScript support.
Resizable
Accessible resizable panel groups and layouts with keyboard support. Built for React applications with Next.js integration and TypeScript support.