Tabs

Switches between a few views on the same page.

Examples

Activity

24 transactions this month.

Money in and out

$1,284.60

in May

States

  • rest

  • hover

  • focus-visible

  • disabled

Usage

When to use it
Use
Two to five views of the same collection: Activity, Scheduled, Shared.
Use
Panels of one screen where one is wanted at a time.
Not for
Setting a value, such as a layout or a unit. Use Segmented.
Not for
A long list of sections that open in place. Use Accordion.
Not for
Moving to another page with its own address. Use links.

Rules

7 rules
Must
Make tabs parallel views of one thing, not unrelated sections. Because people expect every tab to show the same data another way, so Help there goes unfound.
Never
Use Tabs to set a value such as grid or list; use Segmented. Because Tabs announce a tab and a panel, so a view setting is read as a section change.
Must
Name a tab in one or two words in sentence case. Because labels never wrap, so a long one truncates at 192px and loses its last words.
Never
Restyle tabs as filled pills; the underline tells them from Segmented and Chip. Because a lime pill reads as the primary action or a filter chip, not a view.
Must
Keep five tabs or fewer. Because the row neither wraps nor scrolls, so a sixth tab squeezes every label to an ellipsis.
Must
Leave TabsContent focusable so a keyboard user can reach and scroll a text panel. Because a panel of plain text has no other tab stop, so arrow keys cannot scroll it.
Should
Show loading and errors inside the panel; the tab switches at once.

Accessibility

4 checks
TabsList is role tablist, each tab role tab with aria-selected, and each panel role tabpanel.
Tab enters the list on the selected tab; arrows move; Tab then goes to the panel.
Arrow keys follow the reading direction in RTL.
The underline is a background fill, so forced colors may drop it; check in emulation.

Edge cases

6 edge cases
Long label
The label truncates; the row stays inside its container and does not scroll.
Narrow container
The triggers share the width and their labels truncate.
Right to left
The row reverses and the underline positions from the start edge.
Reduced motion
The underline jumps with no slide.
Empty panel
The tab still switches; an unlabeled tab is an unnamed button.
Tabs inside tabs
Valid but confusing; avoid.

API

5 props
Tabs
Base UI Tabs.Root props
TabsList
Base UI Tabs.List props
TabsTrigger value
string default required
TabsTrigger disabled
boolean default false
TabsContent value
string default required

Tokens

11 tokens
--line
#e6e4df
--fg-3
#6b6a63
--fg
#0f0f0d
--fg-disabled
#a6a49b
--ink
#0f0f0d
--text-sm
14px
--weight-medium
500
--control-md
40px
--dur-base
200ms
--dur-instant
80ms
--ease-out
cubic-bezier(0.16, 1, 0.3, 1)

Install

For your coding agent

GitHub

Please star me pookie

141

A new design system every week

Leave your email before you copy the prompt.