Design System

V2 audit — Navigation

Two controls that look similar and mean different things: Tabs switch panels of content, SegmentedControl switches the view of one content set.

Tabs

V2

Switches between sibling panels of content within one page.

TabsTabListTabTabPanel

Live component

Admitted 14 March 2026 · Room B-114 · Key worker Amara Okafor.

Legacy mapping

Legacy modules used underlined tabs, pill tabs and button rows interchangeably. V2 keeps one underlined tab set.

Tabs — standardized specification
AttributeSpecification
DefaultUnderlined, size="medium"
Variantsunderlined · with counts · with icons
Sizessmall · medium
Statesdefault · hover · focus-visible · active · disabled
Icon behaviourOptional leading icon at `--size-icon-sm`; counts render as a Badge, never a raw parenthesis.
SpacingTab padding 12/16px; list gap 4px; 1px bottom rule spans the row.
Typography`text-label-md`; the active tab gains weight, not size.
Border radiusNone on the tab; the indicator is a 2px underline.
Colour usageActive `text-text-primary` + `bg-primary` indicator; rest `text-text-secondary`.
ResponsiveHorizontally scrollable with edge fade below `md`; never wraps to two rows.

When to use

  • Peer sections of one record
  • 3–7 panels

When not to use

  • Navigating to another page
  • Switching how the same data is displayed

Accessibility

  • Radix Tabs roving focus, `aria-controls`/`aria-labelledby` wiring, Home/End support.
  • Visible `ds-focus-ring` on `:focus-visible`; never focus-suppressed.

SegmentedControl

V2

Switches the view, density or range of one content set. Always one option selected.

SegmentedControlSegment

Live component

Legacy mapping

Legacy screens used attached button rows with manual active styling and no keyboard semantics. V2 replaces them with a real single-select toggle group.

SegmentedControl — standardized specification
AttributeSpecification
Defaultsize="medium", fullWidth=false
Variantstext · icon + text · icon only (labelled)
Sizessmall (24px) · medium (32px) · large (40px)
Statesdefault · hover · focus-visible · selected · disabled
Icon behaviourIcon at `--size-icon-xs|sm` matched to the segment size; icon-only segments need `aria-label`.
SpacingTrack padding 4px, segment gap 4px, segment padding 10/12/16px.
Typography`text-label-sm|md|lg`, weight 500.
Border radius`rounded-md` track, `rounded-sm` segments.
Colour usageTrack `bg-background-subtle`; selected segment lifts to `bg-surface` with `shadow-xs`.
Responsive`fullWidth` splits the row evenly on mobile; falls back to a Select above ~4 options on narrow screens.

When to use

  • Day / week / month, list / board, chart type

When not to use

  • Independent toggles — use ToggleGroup multiple
  • Distinct content panels — use Tabs

Accessibility

  • Radix ToggleGroup single-select; empty selection is rejected so a view is always active.
  • Visible `ds-focus-ring` on `:focus-visible`; never focus-suppressed.

ToggleGroup

V2

Formatting-style toggles, single or multiple, rendered as an attached button set.

ToggleGroupToggleGroupItem

Live component

Legacy mapping

Legacy editors used ad-hoc active classes on buttons.

ToggleGroup — standardized specification
AttributeSpecification
Defaultvariant="default", size="medium"
Variantssingle · multiple · default · outline
Sizessmall · medium · large
Statesoff · on · hover · focus-visible · disabled
Icon behaviourIcon size follows the group size; icon-only items require an accessible name.
SpacingItems butt together with -1px overlap.
Typography`text-label-sm|md|lg`.
Border radiusOuter corners `rounded-md`.
Colour usageSelected `bg-primary` + `text-primary-foreground`.
ResponsiveWraps to a second row rather than shrinking targets.

When to use

  • Alignment, formatting, filter toggles

When not to use

  • Primary view switching — use SegmentedControl

Accessibility

  • Radix ToggleGroup semantics; group needs `aria-label`.
  • Pointer target ≥24px (≥44px on coarse pointers) via `ds-target`.