Radio Group
Choose exactly one option from a small set of visible choices.
@garn/ui/radio-groupOn this page
Default
Three labeled options, one preselected.
Sizing
Radio dot size (fixed --garn-box-* geometry, identity); set on the root, propagated to items.
States
Interactive states, toggled live.
Installation
garn is copy-in — the garn CLI writes this component's source into your project, so you own and can edit it. It resolves any base files and installs the npm dependencies below for you.
npx garn-ui add radio-group- Registry
radio-group- Deps
@radix-ui/react-radio-groupclass-variance-authoritylucide-react- Registry deps
utils
Import
import { RadioGroup, RadioGroupItem } from "@garn/ui/radio-group";Anatomy
The parts this component is built from — compose them to assemble it.
RadioGroupRequired[data-slot="radio-group"]Root — owns the selected value and the size (propagated to items).
RadioGroupItemRequired[data-slot="radio-group-item"]One option; needs a unique value. Pair each with a Label.
Props
The component's public props and their types.
size- Description
- No description.
- Type
"lg" | "md" | "sm"- Default
md
Plus 288 inherited native HTML attributes.
Styling
Target these data-slots and states, and remap these tokens, to restyle without forking the component.
[data-slot="radio-group"]States
| Selector | State | Description |
|---|---|---|
[data-state=checked] | checked | Selected item shows its filled dot. |
:focus-visible | focus-visible | 2px ring + offset. |
[disabled] | disabled | Dims and blocks selection. |
| Property | Token | Tier |
|---|---|---|
size | --garn-box-md | semantic · identity |
fill | --garn-brand-solidbrandable | semantic |
ring | --garn-ringbrandable | semantic |
When to use
Pick one option from a few (≈2–5) mutually exclusive choices, all visible at once.
Reach for something else when
- A long list (use select)
- independent on/off items (use checkbox)
- a single instant setting (use switch).
Overview
RadioGroup lets a person pick exactly one option from a few mutually-exclusive choices that are all worth showing at once (≈2–5). RadioGroup owns the selected value and propagates size to each RadioGroupItem. Once the list grows past a handful or the options stop fitting on screen, switch to Select; for a binary on/off setting, a Switch or single Checkbox reads better than two radios.
Guidelines
Always show one option as selected. A radio group should have a sensible default rather than starting empty — an all-blank group makes "no choice" look like a valid state when it usually isn't. Give each RadioGroupItem a unique value and its own Label.
Keep options parallel and exhaustive. Phrase choices in the same grammatical form and at the same level of specificity, and cover the full space (add an "Other"/"None" when the set isn't complete). Order them logically — by magnitude, frequency, or convention — not at random.
Don't use radios for multi-select or instant actions. Several selectable items → Checkboxes; a setting that takes effect immediately → Switch. Arrow keys move selection within the group (roving focus), so don't nest interactive controls inside an item.
Best practices
- Give every RadioGroupItem a unique value and a clickable Label.
- Pre-select a sensible default with defaultValue when one exists.
- Don't use radios for many options — switch to a select past ~5.
- Don't use radios for multi-select — that's checkboxes.
Content guidelines
- Write parallel option labels in sentence case (“Standard”, “Express”, “Overnight”).
- Order options logically (by speed, price, or frequency) and lead with the most common.
- Add a short helper line to an option only when the trade-off isn't obvious from the label.
Troubleshooting
Selecting an option does nothing.
Cause. Passing value without onValueChange makes the group controlled and frozen.
Fix. Use defaultValue for uncontrolled, or pass value + onValueChange.
Accessibility
- Role
radiogroup- ARIA APG
- radio group
- Focus
- Roving tabindex; arrow keys move + select within the group.
Accessibility requirements
Label the group and each option (a Label per item, plus a group label).
when the group has no accessible name (aria-labelledby / aria-label) and items have no labels
Keyboard
| Tab | Move focus into the group (lands on the selected, or first, radio). |
| ArrowUpArrowDownArrowLeftArrowRight | Move to and select the next/previous option. |
- role=radiogroup wraps role=radio items; label the group (aria-labelledby / a Label).