Navigation@knitui/components
Tabs
Tabs organises content into labelled panels. Compose Tabs.List + Tabs.Tab with matching Tabs.Panel elements. variant styles the indicator, orientation switches the axis, inverted places the list after the panels, and placement controls which side the list sits on when vertical.
import { Tabs } from "@knitui/components";Usage
Tabs is a compound component: a Tabs.List of Tabs.Tabs, and a Tabs.Panel
for each one. The value on a tab and its panel are what pair them — there is no
index to keep in sync.
import { Tabs } from "@knitui/components";
<Tabs defaultValue="general">
<Tabs.List>
<Tabs.Tab value="general">General</Tabs.Tab>
<Tabs.Tab value="billing">Billing</Tabs.Tab>
</Tabs.List>
<Tabs.Panel value="general">Account settings</Tabs.Panel>
<Tabs.Panel value="billing">Cards and invoices</Tabs.Panel>
</Tabs>;Leave value off for uncontrolled tabs, or pass value + onChange to drive it
yourself. orientation="vertical" moves the list to the side (placement picks
which side), and inverted puts it after the panels.
By default inactive panels stay mounted and hidden (keepMounted), so state
inside a panel survives switching away from it. Set keepMounted={false} when a
panel is expensive — a map, a chart, a video — and should not exist until it's
selected.
When to use something else
- Panels that expand in place rather than replacing each other →
Accordion - A small set of mutually exclusive values, not views →
SegmentedControl - Navigating between routes →
NavLink
Examples
Variants
All three visual variants side by side.
Loading example…
Sizes
Full token size scale.
Loading example…
Shadows
The shadow elevation prop, inherited from Box, applied to the Tabs root.
Loading example…
Themed
Accent theme comes from Tamagui's theme prop.
Loading example…
With Disabled Tab
A disabled tab cannot be activated and is visually dimmed.
Loading example…
With Sections
Tabs with left/right icon sections for visual adornment.
Loading example…
Vertical
Vertical orientation with the list on the left side (default placement).
Loading example…
Vertical Right
Vertical orientation with the tab list placed on the right side.
Loading example…
Inverted
Inverted layout — the tab list renders below the panel content.
Loading example…
Controlled
Controlled — the active tab is owned by the parent component.
Loading example…
Growing Tabs
grow makes tabs expand to fill the full width of the list.
Loading example…
Styles
Per-slot styles targets individual parts — here the tab, label and panel.
Loading example…
Props
| Prop | Type | Default | Description |
|---|---|---|---|
activateTabWithKeyboard | boolean | undefined | true | When an arrow key focuses a tab, also activate it. `false` = manual activation (focus moves, selection follows on Enter/Space). Web-only. |
allowTabDeactivation | boolean | undefined | false | Allow clicking an active tab to deselect it. |
children | ReactNode | — | `Tabs.List` + `Tabs.Panel` children. |
defaultValue | string | null | undefined | general | Uncontrolled initial value. |
disabled system | boolean | undefined | — | — |
id | string | undefined | — | Base id for a11y ids. Auto-generated if omitted. |
inverted | boolean | undefined | false | Render the tab list after the panels. |
keepMounted | boolean | undefined | true | Keep inactive panels mounted (hidden) in the DOM. |
loop | boolean | undefined | true | Wrap arrow-key roving focus at the ends. |
onChange | ((value: string | null) => void) | undefined | — | Called when the active tab changes. |
orientation | TabsOrientation | undefinedhorizontal · vertical | 'horizontal' | Layout axis of the tab list. |
placement | TabsPlacement | undefinedleft · right | 'left' | Side the list sits on when orientation is vertical. |
radius system | string | number | undefined | — | — |
shadow system | "xs" | "sm" | "md" | "lg" | "xl" | "xxs" | "xxl" | undefined | — | — |
size system | "xs" | "sm" | "md" | "lg" | "xl" | "xxs" | "xxl" | undefinedxxs · xs · sm · md · lg · xl · xxl | 'md' | Size of tab labels and spacing. |
styles system | SlotStyles<TabsStyles> | undefined | — | Uniform per-slot style passthrough — sugar over the composable parts. Slots: `list` / `tab` / `label` / `section` / `panel`. Distributed through context so it reaches every nested `Tabs.Tab`/`Tabs.Panel`. Explicit inline props on a composed part always win. |
theme system | ThemeName | null | undefined | — | Applies a theme to this element |
value | string | null | undefined | — | Controlled active tab value. |
variant system | TabsVariant | undefineddefault · outline · pills | 'default' | Visual style of the tab indicator. |
Style slots
Every part of Tabs can be styled through the styles prop. Explicit props on the component always win over slot styles.
| Slot | Targets |
|---|---|
label | Props for the label text inside each tab (.Tab label). |
list | Props for the Tabs.List row (.List). |
panel | Props for each Tabs.Panel (.Panel) — its stylable frame surface; value/children are the part's own (identity + content). |
section | Props for the left/right section wrapper inside each tab (.Section). |
tab | Props for each Tabs.Tab trigger (.Tab) — its stylable frame surface. active/disabled/size/variant are state/context-driven and value/ children are the part's own, so the sugar targets the frame like siblings. |
Accessibility & DOM props (2)
| Prop | Type |
|---|---|
key | Key | null | undefined |
ref | Ref<TamaguiElement> | undefined |
Plus 495 inherited style props from Box — the full Tamagui/React Native style surface, including token shorthands like p, mx, bg and c. See Tokens for the scales they accept, or the full list.
Accessibility
On the web Tabs implements the ARIA tabs pattern: the list is a tablist, each
tab a tab owning its panel via aria-controls, and each panel a tabpanel
labelled by its tab. Ids are generated for you, or derived from the id prop.
Focus is managed with a roving tabindex — only the active tab is in the tab order, so Tab moves past the whole list rather than through every tab in it, and the arrow keys move within it.
| Key | Action |
|---|---|
| Tab | Move into the tab list, then out to the active panel |
| → / ← | Previous / next tab (horizontal orientation) |
| ↓ / ↑ | Previous / next tab (vertical orientation) |
| Home / End | First / last enabled tab |
| Enter / Space | Activate the focused tab |
Two behaviours are worth choosing deliberately:
activateTabWithKeyboard(defaulttrue) selects a tab as soon as an arrow key focuses it — automatic activation, which ARIA recommends when switching is instant. Set it tofalsefor manual activation (focus moves, selection waits for Enter or Space) when a panel is expensive to render, so arrowing across the list doesn't mount four panels on the way past.loop(defaulttrue) wraps focus at the ends of the list. Turn it off when the list is long enough that wrapping is disorienting.
Disabled tabs are skipped by arrow navigation and are never focused.