Segmented controller

Switches between a few views, ranges or sites, as tabs or pills, with every option in view.

Refined portVue source: WildSegmentedController.vueStorybook story: Buttons/Segmented ControllerReact component: WSeg

Try it

Pick a segment, or tab in and use the arrow keys. Turn off Interactive to see the display-only row.

Variant
Size
Orientation
Full width
Interactive
<WildSegmentedController
  v-model="value"
  :tabs="ranges"
  variant="underline"
  size="md"
/>

When to use

  • Use underline to switch between views of one subject, such as Readings and Alarms.
  • Use pills to re-cut the same view, such as a chart’s window: 24 h, 7 days, 30 days.
  • Use tabs to switch between things of one kind, such as four sites.
Don’t use it

Variants

Underline is the default. Pills sit in a recessed track, and tabs mark the chosen one with a bold label over a sliding bar.

underline
pills
tabs
<WildSegmentedController v-model="view"
  :tabs="views" variant="underline" />
<WildSegmentedController v-model="range"
  :tabs="ranges" variant="pills" />
<WildSegmentedController v-model="site"
  :tabs="sites" variant="tabs" />

Entity tabs

Give each tab a status dot, so a site that stopped reporting shows before anyone opens it.

<WildSegmentedController v-model="site" variant="tabs" full-width
  :tabs="[{ id: 'b12', label: 'Bore 12', dot: 'error' }, …]" />
Entity tabs list things; view tabs list ways of looking at one. Keep them in separate strips, so people know what they’re changing.

Sizes

Three, with 12, 13 and 14px labels. Tabs are 32, 40 and 44px tall. The default is md.

sm
md
lg
tabs · sm
tabs · md
tabs · lg

Orientation and width

Stack the options in a column for a settings panel. Use full width to run the rule edge to edge, or to share the width between pills.

vertical tabs
vertical pills
full width, underline
full width, pills

Badges and disabled segments

Add a count when there’s something to look at before switching. Keep an unavailable segment in place and disabled, so the others don’t move.

Accessibility

With a change handler it’s a tab list, and each segment is announced as a tab, selected or not. Without one it’s a row of labels that takes no focus.

KeyWhat it does
TabMoves focus to the chosen segment.
← / →Chooses the previous or next segment, skipping disabled ones.
↑ / ↓The same, in a vertical strip.
Home / EndChooses the first or last segment.

Props

PropTypeDefaultDescription
v-modelstring—The chosen segment’s id.
tabs{ id, label, badge?, dot?, icon?, disabled?, title? }[]—The segments, in order.
variant'underline' | 'pills' | 'tabs''underline'See Variants.
size'sm' | 'md' | 'lg''md'Label size: 12, 13 or 14px.
orientation'horizontal' | 'vertical''horizontal'A row, or a column.
full-widthbooleanfalseSpans the container.
labelstring—Accessible name for the tab list.

Tokens

TokenValueWhere it lands
--global-blue-1000#1877F2Underline and tabs bar.
--global-blue-300#BDEDFFUnderline hover hint.
--global-blue-1100#0C296AChosen label in underline.
--global-neutral-grey-1300#0A090BChosen label in pills and tabs.
--global-neutral-grey-1000#4F4D55Resting label, every variant.
--global-neutral-grey-500#E6E6E6Underline rule.
--global-neutral-grey-400#ECECEDPills track and tabs rule.
--color-white#FFFFFFChosen pill.
--shadow-xs0 1px 2px 0 rgba(10,9,11,.05)Chosen pill’s lift.
--radius-full9999pxPills track and segments.
(no token)9px / 6pxVertical pills track and segments.
--font-weight-medium475Resting label.
(no token)550 / 600Chosen label; 600 in tabs.
(no token)2.5pxTabs bar.
(no token)7pxStatus dot.