Tabs
Switch between related panels of content.
Organize related content into panels, with a single selected tab at a time. Compose Tabs with direct Tabs.Tab children, each with a unique id.
Import
import { Tabs } from "@puzzle-ui/ui";Basic usage
tab supplies the trigger label, and children supplies the panel content. initialActiveId chooses the initial panel; otherwise the first enabled tab is selected.
Tab bar position
tabBarPosition supports top, bottom, left, and right. Left and right positions use vertical keyboard navigation.
Controlled selection
Use activeId with onActivate to own the selected tab. Do not combine controlled selection with initialActiveId.
Preserve panel state
Inactive panel contents are unmounted by default. forceMountContent keeps them mounted but hidden, preserving local state and uncontrolled form values. Type a note, switch tabs, then return to see it preserved.
Disabled tabs and RTL
Set disabled on a tab to prevent selection and skip it during keyboard navigation. Provide dir="rtl" on Tabs for right-to-left horizontal arrow-key behavior.
API
Tabs
| Prop | Type | Default | Description |
|---|---|---|---|
children | ReactNode | Required | Direct Tabs.Tab children. |
tabBarPosition | "top" | "bottom" | "left" | "right" | "top" | Position and orientation of the tab bar. |
initialActiveId | string | First enabled tab | Initial uncontrolled selection. |
activeId | string | - | Controlled selection. Invalid or disabled IDs fall back to the first enabled tab. |
onActivate | (tabId: string) => void | - | Called when a tab is activated. |
forceMountContent | boolean | false | Keeps inactive panel contents mounted and hidden. |
className | string | - | Additional class on the root div. |
dir | "ltr" | "rtl" | "auto" | - | Root text direction; use explicit rtl for RTL keyboard navigation. |
Other native div attributes are forwarded to the root, except onChange.
Tabs.Tab
TabsTab is also exported as a named alias of Tabs.Tab, with the same props and direct-child requirement.
| Prop | Type | Default | Description |
|---|---|---|---|
id | string | Required | Unique tab identifier. |
tab | ReactNode | Required | Content of the tab button. |
children | ReactNode | Required | Panel content. |
disabled | boolean | false | Prevents focus and selection. |
Accessibility
Tabs use automatic activation: arrow-key focus changes the selected panel. Horizontal tabs use Left/Right; vertical tabs use Up/Down. Home and End move to the first and last enabled tab. Tab buttons expose aria-selected and aria-controls, and each panel is labelled by its trigger.