Description
Tabs organise related content into distinct sections that share a single view. Only one panel is visible at a time; the user selects which to show.
Component detail pages, settings screens, profile views, and any context where discrete categories of content exist at the same level of the hierarchy.
Showing all content simultaneously creates cognitive overload. Tabs allow users to focus on one area at a time while remaining aware that more exists nearby.
Tabs change the visible content within a page; they do not navigate between pages. For navigation, use the sidebar or breadcrumb components.
Anatomy
| Part | Required? | Notes |
|---|---|---|
| Tab list | Required | The container for all tab controls. Receives role="tablist". |
| Active tab | Required | The currently selected tab. Indicated by a visual accent (underline or highlight) and aria-selected="true". |
| Inactive tab | Required | Unselected tabs. Receive aria-selected="false" and tabindex="-1" so they are not in the default tab order. |
| Tab panel | Required | The content region associated with the active tab. Receives role="tabpanel" and is linked to its tab via aria-controls / aria-labelledby. |
Usage guidelines
When to use
- Content divides cleanly into 2–7 parallel sections at the same hierarchy level.
- Users are likely to focus on one section at a time rather than needing to compare across them.
- The tab labels can be short, distinct, and self-explanatory without additional context.
When not to use
- When content should be compared across sections — keep it visible simultaneously.
- When sections form a sequence — use a stepper or wizard pattern instead.
- When there are more than 7 tabs — use a sidebar or dropdown navigation.
- For page-level navigation — tabs are for in-page content switching only.
Do / Don't
Do
Keep tab labels short — one or two words. "Overview", "Activity", "Settings". Users scan tabs, not read them.
Don't
Don't put form elements that affect the whole page inside one tab. Actions that span tabs should live outside the tab component.
Do
Make the default tab the most commonly needed one. Don't default to a tab that's empty or rarely relevant.
Don't
Don't use tabs to create wizard-like flows. If completing step 2 depends on step 1, use a stepper.
Layout & Spacing
| Element | Spec |
|---|---|
| Tab height | 40px |
| Tab padding (horizontal) | --op-space-16 |
| Active indicator | 3px bottom border, --op-color-interactive-default |
| Panel padding | --op-space-20 |
| Label font size | --op-text-sm |
| Active label weight | font-weight: 600 |
| Inactive label colour | --op-color-text-secondary |
| Active label colour | --op-color-text-primary |
| Element | Token |
|---|---|
| Tab list background | --op-color-bg-secondary |
| Active tab background | --op-color-bg-primary |
| Tab border | --op-color-border-default |
| Active indicator | --op-color-interactive-default |
| Focus ring | --op-color-focus-ring, 2px offset |
Engineering notes
- The tab navigation script uses **automatic activation** — selecting a tab immediately shows its panel. If loading a panel is slow or causes layout shift, use **manual activation**: arrow keys move focus between tabs but Enter or Space is required to activate.
- Use
hiddento hide inactive panels, notdisplay: nonevia CSS classes — thehiddenattribute is semantically meaningful to assistive technology. - The
aria-labelon the tablist describes the set of tabs as a whole ("Project details", "Component settings"). Don't duplicate individual tab labels.
Keyboard interaction
| Key | Action |
|---|---|
| Tab | Moves focus to the active tab (first pass), then into the panel content on the next press. Inactive tabs are skipped in the tab order. |
| Arrow Right / Arrow Left | Moves focus between tabs. Wraps at either end. |
| Home | Moves focus to the first tab. |
| End | Moves focus to the last tab. |
| Enter or Space | Activates the focused tab (required for manual-activation mode; optional in auto-activation mode). |
Why it matters
Tabs have a specific keyboard pattern that differs from most components. Unlike a list of links, tabs use arrow keys to navigate between them — not Tab. This is intentional: it lets keyboard users skip past the entire tab list in one press when they want to reach the panel content directly. Deviating from this pattern breaks the experience for users who rely on assistive technology.
ARIA
| Role or attribute | When to use | Example |
|---|---|---|
| ||
| ||
| ||
| ||
| ||
| ||
|
Things to avoid
- Don't make all panels visible simultaneously to assistive technology — use
hiddenon inactive panels. - Don't use
<a href>elements as tabs unless they genuinely navigate to a new URL. Tab controls should be<button>elements. - Don't put the focus indicator only on the active indicator underline — the full tab must receive a visible focus ring.