# Tabs One strip, several panels. - Group: Navigation - Import: `import { Tabs } from '@misoto22/folio'` - Page: https://ui.misoto22.com/components/tabs/ - Related: accordion ## Anatomy - **Root** (required) — Tabs — Radix’s root, re-exported. It draws nothing and owns everything: value or defaultValue, and activationMode. With neither value nor defaultValue no tab is selected and no panel is mounted. - **Tab strip** (required) — TabsList — the role="tablist" row, sitting on one hairline rule and scrolling on its own axis with scroll-slim. It has no accessible name unless you give it one. - **Tab** (required) — TabsTrigger, at the md control height with its label on one line. Every tab carries the 2px active marker, transparent until it is the selected one; the marker is pulled onto the strip’s own border with -mb-px so the two share a line rather than stacking into a 3px edge. - **Panel** — TabsContent, paired to its tab by matching value. Mounted only while it is the selected one, and marked data-folio-animated so its entrance is dropped for a reader who asked for less motion. ## Best practices ### Do - Give the root a defaultValue or a value: with neither, nothing matches, every panel stays unmounted, and the page renders a strip above an empty space with nothing to say what is missing. - Match each trigger’s value to a panel’s value exactly — the pairing is string equality, and a typo is not an error but a tab that opens onto nothing. - Pass activationMode="manual" when a panel fetches or renders something expensive: the default is automatic, so ← and → select as they move and arrowing across four tabs starts four loads before the reader has stopped. - Give TabsList an aria-label on a page with more than one set: Radix names the tablist after nothing, and two unnamed tablists are two “tab list”s a reader cannot tell apart. ### Don’t - An unselected panel is unmounted, not hidden — find-in-page cannot reach its text, a print takes only the panel that was open, and a half-filled form in another tab has lost what was typed into it by the time the reader comes back. - The selected tab lives in React state, not in the URL: a reader who reloads or shares the page lands on the first panel, so anything worth linking to needs value lifted into a query parameter. - Tabs are not a way to fit more in: the strip scrolls silently, and a sixth tab past the fold looks exactly like a page that only has five. ## Accessibility - The strip scrolls rather than wrapping: a wrapped second row moves every tab below it and the reader loses the one they were about to click. - 44px tall, because a tab is a pointer target like any other. ## Keyboard - Tab — Moves into the strip, and out of it — the whole strip is one stop. - ← / → — Moves between tabs and switches the panel with them. - Home / End — Jumps to the first or last tab. ## Tabs Accessible tabs with a moving marker and optional horizontal drag gestures. ## TabsList The tab strip. Scrolls horizontally rather than wrapping. A wrapped second row of tabs moves every tab below it when the strip grows, and the reader loses the one they were about to click. ## TabsTrigger One tab. The active marker is a 2px ink rule pulled onto the strip's own border with `-mb-px`, so the two occupy the same line instead of stacking into a 3px edge. 44px tall, because a tab is a pointer target like any other. ## TabsContent The panel paired to a TabsTrigger by matching `value`. ## Example — default ```tsx import { Tabs, TabsContent, TabsList, TabsTrigger } from '@misoto22/folio' Preview Code Props The rendered component. The source that produced it. Its parsed prop table. ``` ## Example — manual activation ```tsx import { Tabs, TabsContent, TabsList, TabsTrigger, Text } from '@misoto22/folio' Traffic Referrers Errors 18,402 visits over the last 30 days, up 6% on the month before. news.ycombinator.com sent 4,110 of them; nothing else broke 500. Eleven 500s, all from the same deploy, all before 09:14. ``` ## Example — what gets hidden ```tsx
Tabs — one of several views USD AUD Billed at $18 a seat each month. Billed at A$28 a seat each month.
Accordion — a set of answers Billed at $18 a seat each month. Yes, and the remainder is refunded.
Collapsible — detail on one thing
Billed at $18 a seat each month, on the day you first subscribed.
```