Basel Standard / Docs
Radio Group
Single-choice selection control for mutually exclusive options inside forms, settings, and workflow routing.
Visible to the internal review group before general rollout.
Keeps the issue in editorial review until dependencies are resolved.
Radio groups are for decisions where exactly one option should define the state. The Swiss wrapper keeps the Radix keyboard and accessibility behavior, then reduces the visual treatment so the label and supporting copy can carry the real comparison.
Installation
Purchase access, then open /account/install to issue a registry token.Usage
import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group"
import { Label } from "@/components/ui/label"
<RadioGroup defaultValue="public">
<label className="flex items-center gap-3">
<RadioGroupItem value="public" id="public" />
<Label htmlFor="public">Public issue</Label>
</label>
<label className="flex items-center gap-3">
<RadioGroupItem value="private" id="private" />
<Label htmlFor="private">Subscriber issue</Label>
</label>
</RadioGroup>
Why This Primitive Exists
Radio groups solve the cases where a checkbox would imply independence and a select would hide the comparison.
- Use them when the user should compare a short list of mutually exclusive options before choosing one.
- Prefer them to a select when the option meaning benefits from visible supporting copy.
- Avoid them for long lists or cases where multiple options may be true at once.
Examples
Basic Choice
This is the smallest useful pattern: one value group, one clear default, and labels that explain the consequence.
Best for public updates with approved copy and locked assets.
Visible to the internal review group before general rollout.
Keeps the issue in editorial review until dependencies are resolved.
<RadioGroup defaultValue="stable">
<label className="flex items-center gap-3">
<RadioGroupItem value="stable" id="stable" />
<Label htmlFor="stable">Stable release</Label>
</label>
</RadioGroup>
Form Rows
Radio groups become more legible when each choice owns a full row with a short explanation. This is a better fit than collapsing that guidance into placeholder text or a tooltip.
Single decision
Each row explains the implication so the user can compare before committing.
Preserves the issue sequence defined by the editorial team.
Moves new stories to the top as they are published.
Pins one story, then follows the standard chronological order.
<RadioGroup defaultValue="curated" className="gap-0 border border-border">
<label className="flex items-start justify-between gap-4 p-4">
<div className="grid gap-1">
<Label htmlFor="curated">Curated order</Label>
<p className="text-sm text-muted-foreground">
Preserves the sequence defined by the editorial team.
</p>
</div>
<RadioGroupItem value="curated" id="curated" className="mt-1" />
</label>
</RadioGroup>
In Context
Use radio groups inside publishing or configuration flows when the choice changes how the next step behaves.
Release routing
The control stays quiet while the supporting copy carries the operational difference.
Publishes to the private issue archive without updating the public index.
Adds the release to the public archive and sends the editorial summary.
Guidance
Prefer Visible Comparison For Short Lists
- Use radio groups when the list is short enough to scan without scrolling.
- If each option needs one or two lines of explanation, radios are usually clearer than a collapsed select.
- If the list is long, searchable, or grouped into many sections, switch to
Select.
Keep Labels And Values Stable
- Make the visible label describe the resulting state, not the interaction.
- Keep option copy parallel so the differences are easy to compare.
- Use stable
valuestrings because forms and workflow logic often depend on them directly.
Pair With Nearby Context
- Wrap the control and label in a clickable row when space allows.
- Add supporting text outside the indicator so the radio mark stays small and quiet.
- Use one radio group per decision. If two questions are unrelated, split them into separate groups.
API Reference
Exports
| Export | Renders | Notes |
|---|---|---|
RadioGroup | RadioGroupPrimitive.Root | Grid wrapper for the related options. |
RadioGroupItem | RadioGroupPrimitive.Item | Single radio control with the Swiss border, focus, and indicator treatment. |
Notable Props
| Export | Prop | Type | Notes |
|---|---|---|---|
RadioGroup | value, defaultValue | string | Controlled or uncontrolled selected value. |
RadioGroup | onValueChange | (value: string) => void | Fires when the chosen item changes. |
RadioGroup | name | string | Useful when the selection participates in form submission. |
RadioGroup | disabled, required | boolean | Forwarded to the Radix root. |
RadioGroupItem | value | string | Required unique value for each option. |
RadioGroupItem | disabled | boolean | Disables one option without disabling the full group. |
RadioGroupItem | className | string | Extends the base Swiss indicator styling. |
Visual Behavior
| State | Behavior |
|---|---|
| default | Circular border with no fill until selected. |
| checked | Inner dot appears using the foreground color. |
| focus visible | Adds the stronger inset ring treatment. |
| disabled | Reduces opacity and removes pointer affordance. |
The wrapper is otherwise a thin layer over Radix Radio Group, so standard root and item props continue to work.