figma guide
Designing segmented controls and radio groups in Figma: patterns, states, and handoff
Design segmented controls and radio button groups in Figma with exclusive selection, responsive layouts, icon+label segments, and Dev Mode specs for settings and forms.
- Published
- Updated
- Jun 15, 2026
- Read time
- 7 min
- Level
- Beginner
Quick answer
Radio groups and segmented controls both enforce exactly-one selection—but segmented controls show every option at once as a connected pill bar, while radio groups stack individual circles with labels. Build a Radio primitive (selected=off | on, state=default | focus | error | disabled) and a SegmentedControl container with Segment children (position=first | middle | last, selected=off | on). Use radios for long option lists and forms; use segmented controls for 2–5 compact choices (view mode, billing cycle, chart range). Pair with forms, checkboxes and switches, and navigation tabs when the pattern blurs. Document keyboard arrows, default selection, and whether change applies instantly in Dev Mode. Start from the Figma guides hub.
Who this is for
- Product designers shipping pricing pickers, chart ranges, layout toggles, and wizard steps.
- Design system teams drawing the line between tabs, segmented controls, and radio lists.
- Engineers implementing roving tabindex,
role="radiogroup", and responsive overflow behavior.
Radio group vs segmented control vs tabs
| Pattern | Options visible | Selection | Navigation? | Best for |
|---|---|---|---|---|
| Radio group | Vertical/horizontal list | One of N | No | Forms, settings with descriptions |
| Segmented control | All segments in one bar | One of 2–5 | No | Compact filters, view mode |
| Tabs | Tab labels | One panel | Yes—swaps content | Navigation |
| Dropdown | Hidden until open | One of many | No | >5 options—use dropdown |
| Chip filter (single) | Scrollable row | One active | Sometimes | Mobile overflow |
Verdict: if switching content panels, use tabs. If picking one value inside the same view (list vs grid), use a segmented control. If options need helper text per row, use radio group.
Radio button component anatomy
| Part | Purpose | Spec tip |
|---|---|---|
| Outer circle | Unselected ring | 16–20px diameter |
| Inner dot | Selected fill | 8–10px centered |
| Label | Option name | Clickable; supports wrap |
| Description | Secondary copy | Below label for plans |
| Group label | Question | legend / heading above set |
Radio
├── Variant: selected=off | on
├── Variant: state=default | focus | error | disabled
├── Variant: size=sm | md
├── Layer: Row (auto layout horizontal)
│ ├── Circle (stroke ring)
│ │ └── Dot (visible when selected)
│ └── LabelBlock
│ ├── Label
│ └── Description (optional)
└── Layer: Group error (shared, below set)
Use auto layout vertical stacks with 12px gap between radio rows.
Radio states
| State | Circle | Label | Notes |
|---|---|---|---|
| Unselected | Empty ring | Default | Neutral border |
| Selected | Ring + filled dot | Default | Dot uses brand color |
| Focus | Focus ring | Unchanged | Ring on entire row acceptable |
| Error | Error ring | Error optional | Group-level message common |
| Disabled | Muted ring | Muted text | Entire option inactive |
Only one radio in a group should show selected=on unless documenting an invalid mock.
Segmented control anatomy
| Part | Purpose | Spec tip |
|---|---|---|
| Container | Groups segments | Pill background; 4–8px padding |
| Segment | One option | Equal width or hug content |
| Selected fill | Active segment | Raised or inverted surface |
| Icon | Optional | 16px with label or icon-only |
| Divider | Between segments | 1px line or gap—pick one system |
SegmentedControl
├── Variant: size=sm | md
├── Variant: fullWidth=true | false
├── Layer: Container (auto layout horizontal, padding 4)
│ └── Segment × N
│ ├── Variant: selected=off | on
│ ├── Variant: position=first | middle | last | only
│ ├── Icon (optional)
│ └── Label
└── Layer: Helper / error (optional)
Position variants control corner radius: first segment rounded left, last rounded right, middle square—so the bar reads as one unit.
Segmented control states
| State | Container | Active segment | Inactive segment |
|---|---|---|---|
| Default | Neutral track | White or elevated fill | Transparent on track |
| Hover | Unchanged | Subtle background | Hover tint |
| Focus | Unchanged | Focus ring on segment | Focus ring on segment |
| Disabled | Muted track | Cannot select | Muted text |
| Icon-only | Same | Tooltip required | Tooltip on hover |
For icon + label segments, collapse to icon-only on narrow breakpoints—document breakpoint in Dev Mode.
Layout patterns
| Pattern | Control | Layout |
|---|---|---|
| Vertical radio list | Radio | Stack; descriptions under labels |
| Horizontal radio row | Radio | 2–3 short options only |
| Full-width segmented bar | Segmented | fullWidth=true; equal segments |
| Hug-content pill | Segmented | Chart range: 1W / 1M / 1Y |
| Inside toolbar | Segmented | Next to search |
| Pricing cards | Radio | Large card with border selection state |
Pricing cards are often radio-backed even when they look like cards—add a selected border variant and document role="radio" on the card container.
Pairing with other patterns
| Need | Pattern | Link |
|---|---|---|
| Form submit | Radio group + validation | Forms |
| Settings instant apply | Segmented control | Switches nearby |
| Multi-select filters | Not radio—use checkboxes | Checkbox guide |
| Wizard steps | Radio for plan pick | Progress steppers |
| Mobile overflow | Scrollable chips or dropdown | Dropdown menus |
| Chart / dashboard | Segmented range | Tables toolbar |
Accessibility checklist
| Requirement | Radio group | Segmented control |
|---|---|---|
| Container role | role="radiogroup" | role="radiogroup" or role="tablist" only if switching panels—prefer radiogroup |
| Item role | role="radio" | role="radio" per segment |
| Selection | `aria-checked=“true | false”` |
| Label | aria-labelledby on group | aria-label on container |
| Keyboard | Arrow keys move selection | Arrow keys between segments |
| Focus | Roving tabindex | One tab stop on group |
| Disabled option | aria-disabled | Gray segment skipped in arrows |
Test contrast on inactive segment text on tinted tracks—common failure in dark mode. Use dark mode tokens and a11y plugins.
Prototyping limits
Figma does not enforce exclusive selection across separate instances. Approaches:
- Component set with
selectedproperty on one SegmentedControl—swap segments via variants. - Separate frames per selected segment for static screenshots.
- Overlays for radio card selection (selected border frame on click).
Use interactive components for hover on segments; document that only one may be active in production.
Handoff to engineering
| Deliverable | Radio | Segmented |
|---|---|---|
name | group name | control id |
value per option | string | string |
defaultValue | pre-selected option | pre-selected segment |
onChange | callback with value | callback with value |
orientation | vertical / horizontal | horizontal (usually) |
fullWidth | n/a | boolean |
disabled | per option or whole group | per segment or whole bar |
| Error | group message string | same |
| Responsive | stack on mobile? | icon-only breakpoint |
Add to Dev Mode checklist. Publish primitives in your team library under Patterns / Forms.
Real-world examples
Billing cycle picker (segmented)
Three segments: Monthly / Annual / Lifetime. Annual selected by default; “Save 20%” badge on Annual segment only—not on the container. fullWidth=true on pricing page.
Shipping method (radio list)
Vertical radios with label + description + price right-aligned. Error on submit if none selected: “Choose a shipping method.”
Editor view toggle (segmented icon)
Design / Preview / Code icon-only segments with tooltips. 40px height; md size. Collapses to dropdown under 360px—note in spec.
Common mistakes
| Mistake | Consequence | Fix |
|---|---|---|
| Segmented control with 8 options | Crowded bar | Use dropdown or radio list |
| Tabs for view mode only | Wrong semantics | Segmented control |
| Multiple radios selected in mock | Impossible state | One selected=on per group |
| No default selection | User submits empty | Pre-select sensible default |
| Radio for on/off setting | Needs Save awkwardly | Use switch |
| Unequal segment widths | Jumpy layout | fullWidth + equal flex |
| Icon-only without tooltip | Unknown meaning | Tooltip or aria-label |
| Card selection without radio role | Accessibility gap | Document role="radio" on card |
FAQ
Segmented control or tabs?
Tabs when each option reveals different content. Segmented when the same canvas changes mode (list/grid, $/%).
Radio or checkbox for filters?
Checkboxes when users pick multiple filters. Radio when filters are mutually exclusive (sort: Newest vs Price).
How many segments max?
2–5 in one bar. Beyond that, use vertical radios or a combobox.
Horizontal radios on mobile?
Stack vertically below 480px unless labels are one word each.
Bottom line
Radio groups excel when options need space and descriptions; segmented controls excel when the choice is small, visible, and immediate. Build both with exclusive selection, keyboard rules, and responsive collapse documented in Dev Mode. Continue with forms, checkboxes and switches, navigation tabs, and the tutorials hub.
§ Keep reading