A pill segment control switches between two to four related views or filters in the same surface. A pill slides to the active segment.
Tokens, sizes, measurements, states and requirements. Values come from the live token package and from the specification skill: Pill segment control.
Resolved from the live token package.
| State | Part | Token | Value |
|---|
Open points: the Primary Inverted variant (for black surfaces) and the Square shape are in the Figma spec but not specified or built. The Disabled state must be pulled from Figma (State=Disabled) before it is built. The component is not yet compared against the Figma design.
| Size | Desktop (769px+) | Mobile and tablet | Used for |
|---|---|---|---|
| Large | 56px · padding 5px · radius 28px · pill padding 24px · 18/18, 0.18px | 48px · 4px · 24px · 20px · 16/16, 0.32px | Page-level view switcher |
| Medium | 48px · 4px · 24px · 20px · 18/18, 0.18px | 40px · 4px · 20px · 16px · 16/16, 0.32px | View switcher in a drawer |
| Small | 40px · 4px · 20px · 16px · 16/16, 0.48px | 32px · 3px · 16px · 12px · 14/14, 0.42px | Secondary filters |
| XSmall | 32px · 3px · 16px · 12px · 14/14, 0.56px | 32px · 3px · 16px · 10px · 12/12, 0.48px | Compact filters in a table toolbar |
Columns: height · track padding · track radius · pill padding · text. The track radius is always half the height; the pill radius is the track radius minus the track padding. sm (640–768px) still has the mobile size.
Padding of the track at each size: the space between the track and the pill. The numbers are read from the component.
| Attribute | Large | Medium | Small | XSmall |
|---|---|---|---|---|
| Height, Desktop | 56px | 48px | 40px | 32px |
| Height, Mobile | 48px | 40px | 32px | 32px |
| Track padding, Desktop | 5px | 4px | 4px | 3px |
| Track padding, Mobile | 4px | 4px | 3px | 3px |
| Pill padding (left, right), Desktop | 24px | 20px | 16px | 12px |
| Pill padding (left, right), Mobile | 20px | 16px | 12px | 10px |
| Track radius | Half the height | |||
| Pill radius | Track radius minus the track padding | |||
The spacing values as tokens.
| Part | Value |
|---|---|
| Track padding 4px | space-4 |
| Track padding 3px and 5px | Literals: no spacing token for 3px and 5px |
| Pill padding 12px, 16px, 20px, 24px | space-12, space-16, space-20 (literal), space-24; 10px is a literal |
The segment padding is set in the CSS in pixels. Open point: bind 3px, 5px, 10px and 20px to tokens or add them to the spacing scale.
Hover darkens the track to border-tertiary and underlines the inactive segment. Focus has no style of its own: the buttons use the global keyboard focus ring. Hover is forced on this page.
| State | Control | Rule |
|---|
| Size | Type | Desktop (769px+) | Mobile and tablet |
|---|---|---|---|
| Large | label-lg | 18/18, 0.18px | 16/16, 0.32px |
| Medium | label-lg | 18/18, 0.18px | 16/16, 0.32px |
| Small | label-md | 16/16, 0.48px | 14/14, 0.42px |
| XSmall | label-sm | 14/14, 0.56px | 12/12, 0.48px |
Breuer Condensed, weight 600, uppercase, with ss02 and ss03.
| Element | Class | Notes |
|---|---|---|
| Track | pill-segment-control, --md, --sm, --xs | role="group" with an aria-label. Large is the default. |
| Pill | pill-segment-control__thumb, --light | A separate element. pill-segment-control.js sets its width and translateX. |
| Segment | pill-segment-control__btn, --active | A button with aria-pressed. |
| Type | Class | Use |
|---|---|---|
| Black pill | Default | On light surfaces. |
| White pill | pill-segment-control__thumb--light | When the control already sits on a dark or grey surface. |
| Primary Inverted | — | In Figma, not built. |
| Square shape | — | In Figma, not built. |
Fluid (width: 100%) only below 640px, where the segments share the space evenly. From 640px it shrinks to its content (width: auto, align-self: flex-start). Count: two to four short options on one row.
| Property | Duration | Easing |
|---|---|---|
Pill: transform and width | duration-medium-2 (300ms), set through --sg-duration | ease-standard, set through --sg-ease |
Track background-color on hover | duration-fast-3 | ease-standard |
Segment text color | duration-fast-3 | ease-standard |
The pill travels a visible distance, so it is slower than a hover. Compare other easing and duration values in the live Motion section on Examples & Guidelines.
| Topic | Rule |
|---|---|
| Sliding pill | The pill is its own .pill-segment-control__thumb. pill-segment-control.js sets its width and translateX from the active button’s offsetWidth and offsetLeft, because the buttons can have different widths. It re-measures on resize and load. |
| Event | A bubbling segment-change event with detail.button. |
| Count | 2–4 short options on one row. More: eco-select or eco-radio. |
| Disabled | Not specified. Pull State=Disabled from Figma before building it. |
| Topic | Requirement |
|---|---|
| Markup | role="group" with an aria-label; the buttons carry aria-pressed. |
| Focus | No own style: the buttons use the global focus ring on keyboard focus (border-focus). Never add a second ring (WCAG 2.4.7). |
| Color | The active segment is also shown by the pill, not by color alone. |
| Motion | Reduced motion: the pill slide should be turned off. Open point: the CSS does not yet have a prefers-reduced-motion rule. |