Skip to content

Tabs

The row of tabs.

Beta · Navigation and overlay · packages/css/src/components/tabs.css · React on Base UI: @pepperui/tabs

.pui-tabs (line) · --segment · --small · __trigger with aria-selected · __icon · --on-card.

Tabs — every size and every stateOpen in the workshop

Sizes across, states down.

  • Variant line / segment × Size small / medium
  • The segment’s box follows the Ground mode of the frame it sits in (page · card); line has no box to fill
  • Three exposed triggers — edit labels and states on the instance; hide one for a pair
  • The first trigger is active by default; keep exactly one active
  • The content below is not a component — it is what the tab opens

Use when one of several views must be open — sections of a page (line), or a two-to-four-way mode (segment).

Do not use when the options are actions (Button group), multi-select filters (Chip), or top-level navigation (Sidebar, Topbar).

Relates to Tabs trigger - line, Tabs trigger - segment, Button group, Toggle group, Chip, Sidebar.

Anti-patterns two lists on one card · a list with nothing active · a segment with five options · tabs that scroll · a white box painted by hand on a product screen instead of the frame’s Ground mode.

Keywords: tabs, tablist, segment, strip, sections, panes, mode, ground

Figma — page Tabs: Tabs list (4 variants) · Tabs trigger - line (10 variants) · Tabs trigger - segment (10 variants)

shadcn: tabs

The class, the parts, and nothing that is not in the package. The same block opens tabs.css.

<div class="pui-tabs" role="tablist">
<button class="pui-tabs__trigger" role="tab" aria-selected="true">Charts</button>
<button class="pui-tabs__trigger" role="tab">Images</button></div>
<div class="pui-tabs pui-tabs--segment" role="tablist"> …the same triggers… </div>
What it is Note
Variant (none) line · --segment —
Size --small (12 px) · (none) medium (14 px) —
On card automatic: under [data-ground=“card”] and inside every part that paints surface/card (ground.css) the box is white; in a white Card it is neutral/100, as on any white ground. --on-card is the explicit switch, for a consumer who paints the product ground without setting data-ground. Segment only; line has no box to fill —
State active = [aria-selected=“true”] or [data-state=“active”] · :hover · :focus-visible · :disabled —
Parts __trigger · __icon (line only — a 16 px leading glyph) —

Every number here is measured on the rendered component: contrast (npm run contrast:render), the focus ring (npm run focus) and the keyboard (npm run keyboard). The floors are principle 12’s.

ink on ground reads floor the matrix calls it
#544d4d on #f2f2f2 7.36 4.5 text.muted on surface.sunken (promised) ok
#544d4d on #ffffff 8.24 4.5 text.muted on surface.page (promised) ok
#ffffff on #231b1b 16.88 4.5 text.on-accent on surface.inverse (not-offered) ok
#0b0202 on #ffffff 20.51 4.5 text.default on surface.page (promised) ok

4 distinct pair(s) rendered, 0 that axe calls a violation.

primitive on the indicator over the change
Tabs trigger surface/page shadow #6a66e4 2 px #ffffff 4.53 ok
Tabs trigger surface/card shadow #6a66e4 2 px #f2f2f7 4.06 ok
Tabs trigger surface/sunken shadow #6a66e4 2 px #f2f2f2 4.05 ok

15 of 15 focus stop(s) in this block meet WCAG 2.4.13 on screen — the same crop screenshotted focused and unfocused, and the difference measured.

role tab stops what the pattern requires
tablist .pui-tabs 1 exactly 1 ok
tablist .pui-tabs.pui-tabs--small 1 exactly 1 ok
tablist .pui-tabs.pui-tabs--segment 1 exactly 1 ok
tablist .pui-tabs.pui-tabs--segment.pui-tabs--small 1 exactly 1 ok
tablist .pui-tabs.pui-tabs--segment 1 exactly 1 ok
tablist .pui-tabs.pui-tabs--segment.pui-tabs--small.pui-tabs--on-card 1 exactly 1 ok

What the consumer’s script owes. ONE tab stop: the selected trigger takes tabindex=“0”, every other trigger tabindex=“-1”. The script owes Left / Right to move and select, Home / End for first / last; Tab leaves for the panel.

Tab order across the whole library is document order over 344 stops, and Shift+Tab is its exact reverse — no keyboard trap anywhere (WCAG 2.1.2).

Pepper UI v1.5.0

The Mobupps design system. 386 tokens, 88 components, 65 pages in the workshop — every page of this site generated from the repository, so nothing here is typed twice.