Skip to content
Site volume
Colourway

Components

Tabs

Tabs on a soft baseline; the active tab is bolder and carries a 4 px ink rule, with no reflow.

Import from@maxgrits/overprint-react/tabs
On this page

Example#

Look of this example

Pebblepath sells hand-thrown cups.

Live render of examples/tabs/basic.tsx

Usage#

Use tabs to split related content on one page into panels people read one at a time: a project's overview, its work and its numbers. Every panel should make sense on its own.

  • The active tab is bolder and carries a 4 px ink rule; its width is reserved in advance, so nothing reflows when it changes.
  • Activation. Arrow keys select tabs at once by default; activation="manual" waits for Enter or Space, for panels that are heavy to render.
  • Overflow. A long list scrolls sideways with snap points, keeping the active tab in view. Prefer fewer tabs to scrolling ones.
  • Content people compare belongs side by side, not in tabs. Steps in an order belong in a form or a list, not tabs.

Anatomy#

Pebblepath sells hand-thrown cups.

The parts of examples/tabs/basic.tsx, numbered:
  1. ListThe tab row on a 2 px soft baseline..mk-tabs-list
  2. Active tabWeight 700 and a 4 px ink rule..mk-tab[aria-selected="true"]
  3. PanelFocusable when it holds nothing focusable..mk-tabs-panel

Volume#

Reading layer: identical at every volume.

  • Quiet

    Pebblepath sells hand-thrown cups.

    Docs, forms, legal and long reads. Flat inks, no art in motion.

  • Studio

    Pebblepath sells hand-thrown cups.

    The site default. Art on its own plates, one display moment per view.

  • Press

    Pebblepath sells hand-thrown cups.

    Hero moments, covers and campaigns. Halftone fields and the second ink.

  • Rave

    Pebblepath sells hand-thrown cups.

    Launches, posters and the 404. Every ink, and the words still win.

Content#

  • Tab labels are short nouns, one or two words, in sentence case: "Overview", "Work".
  • Labels name what is in the panel, never what to do ("See work").
  • If a tab would be empty, remove it rather than showing an empty panel.

Do and don't#

Do

Pebblepath sells hand-thrown cups.

Parallel panels about one thing.

Don't

  1. Step 1: your project
  2. Step 2: your budget
  3. Step 3: send

A sequence: steps belong in a form, not tabs.

Tabs promise that panels can be read in any order. A process with an order needs a form with steps, so nobody skips step two.

Accessibility#

  • Arrows, Home and End move between tabs; activation is automatic unless activation="manual".
  • A panel is a tab stop only when it holds nothing focusable.
KeysWhat happens
TabMoves to the active tab, then into its panel
LeftorRightMove between tabs (and select them, unless activation is manual)
HomeorEndJump to the first or the last tab
EnterorSpaceSelect the focused tab (manual activation)

The colour pairs it prints, with their contrast on both papers:

TextSurfaceRoleBoneNight
--mk-ink--mk-paper-hoverbody-ui 17.99:1 · Lc 103.4, passes 16.94:1 · Lc 96.5, passes
--mk-ink--mk-paper-sunken-hoverbody-ui 16.63:1 · Lc 98.0, passes 16.46:1 · Lc 96.3, passes
--mk-ink--mk-paper-plate-hoverbody-ui 16.90:1 · Lc 99.1, passes 16.02:1 · Lc 96.0, passes

Process at Studio, normal contrast. Every look: the press check.

Props#

PropTypeDefaultDescription
valueTabValuenone
defaultValueTabValuenone
onValueChange((value: TabValue) => void)none
activation"automatic" | "manual"none`automatic` (default) selects on arrow keys; `manual` waits for Enter or Space.
children requiredReactNodenone

Plus 277 React and DOM attributes passed through to the root element (className, ref, aria-*, event handlers and the rest). Generated from TabsProps in packages/overprint-react/src/reading/tabs/tabs.tsx.

Tokens#

Changelog#

Arrived in 0.1.0.

0.1.024 October 2026

  • MinorreactThe reading layer's controls, overlays, forms and visitor prefs (P2-T1 to P2-T5): every Button is the comic hit key, with IconButton, Link and Tooltip; Input, Textarea, Select, Checkbox and CheckboxGroup, Radio and RadioGroup, Switch, Slider with the ruler, RulerReadout and SegmentedControl; Dialog, Drawer, NavSheet, Tabs, Disclosure, Faq and faqJsonLd on Base UI 1.9 where the platform falls short; Field, Fieldset, Form with the site's inline validation, ErrorSummary, Callout, Honeypot, FormTimestamp and QuoteForm; PrefsScript under 1 KB, usePref and setPref with cross-tab sync, ThemeToggle and the visitor VolumeDial; VisuallyHidden.
  • PatchreactTabs draw their 2 px baseline with plain fills (each tab under itself and the gap after it, and a filler to the list's end) instead of a background image on the list, so the list paints nothing behind its labels; it still sits at the tabs' foot and the focus ring still prints whole outside the tab. Read the whole entry
  • PatchreactSegmentedControl, Tabs and CodeBlock draw LC-05's ring outside the focused key (2 px at 2 px) instead of inset; RadioGroup and CheckboxGroup keys and cards, VolumeDial stops and link Cards mark the element that draws the ring (data-mk-focus-ring); a focusable VisuallyHidden draws the ring. Read the whole entry