Contents Purpose Anatomy Variants States Tokens Used Accessibility Behavior Default (segmented) Loose variant (`btn-group-loose`) Small size (`btn-group-sm`) Count badge (`btn-group-count`) Selection mode Platform Notes Component: btn-group Purpose Group related toggle buttons into a segmented control or filter bar for mode switching, view selection, or filtering. Supports both single-select (one active) and multi-select (multiple active) modes. Anatomy btn-group — inline-flex container with shared border btn-group-item — individual segment button btn-group-count — optional inline count badge inside a btn-group-item Variants Class Visual Usage btn-group Base — inline segmented container Wraps btn-group-items btn-group-item Individual segment — text label Each option in the group btn-group-item is-active Accent background, surface-primary text Currently selected option(s) btn-group-loose Separated pills with gap, flex-wrap Filter bars, tag-style toggles btn-group-sm Compact padding and font size Dense UIs, secondary controls btn-group-count Subordinate inline count Optional count inside an item States All canonical interactive states apply: rest, hover, focus-visible, active, disabled. Hover (transition: --duration-normal ease-out): btn-group-item: background-color → --color-surface-secondary btn-group-item.is-active: background-color → --color-accent-hover Active (instant, no transition): btn-group-item: background-color → --color-surface-tertiary btn-group-item.is-active: filter: brightness(0.9) Focus-visible: outline: 2px solid var(--color-accent-base) outline-offset: -2px (inset to stay within container bounds) Disabled: opacity: 0.4 pointer-events: none Tokens Used --font-sans, --text-sm, --text-xs --space-1, --space-2, --space-3 --color-accent-base, --color-accent-hover --color-surface-primary, --color-surface-secondary, --color-surface-tertiary --color-text-primary, --color-text-secondary --color-border-default --duration-normal Accessibility Container: role="group" with aria-label describing the control's purpose Items: aria-pressed="true" on active item(s), aria-pressed="false" on others Single-select: JS toggles is-active and aria-pressed so only one item is active at a time Multi-select: each item's is-active and aria-pressed are toggled independently Keyboard: Tab focuses the group, arrow keys move between items (optional enhancement) Behavior Default (segmented) Container: display: inline-flex, border: 1px solid var(--color-border-default), overflow: hidden Items: --space-1 / --space-3 padding (vertical/horizontal), --text-sm, --font-sans Dividers: left border on all items except :first-child Active item: accent-base background, surface-primary text Loose variant (btn-group-loose) Container: flex-wrap: wrap, gap: var(--space-2), no border, overflow: visible Items: surface-tertiary background at rest, text-secondary color, no left border Hover: surface-secondary background Use for filter bars, tag-style toggles, and groups that may wrap across lines Small size (btn-group-sm) Items: --space-1 / --space-2 padding, --text-xs font size Combine with any variant: btn-group btn-group-sm or btn-group btn-group-loose btn-group-sm Count badge (btn-group-count) Optional <span class="btn-group-count"> inside a btn-group-item, after the label text Visually subordinate: --text-xs, opacity: 0.7 (0.85 inside active items) Selection mode Single-select (default): one is-active at a time — JS toggles the active item Multi-select: multiple is-active allowed — JS toggles each item independently Platform Notes Web: CSS in @layer components. One file: btn-group.css. JS handles toggling is-active and aria-pressed. macOS: Map to SwiftUI Picker with .segmented style.