Tabs

Switches between related panels of content in one place.

@paneui/theme@base-ui/reactclass-variance-authority
Conversations with your agent.

Installation

pnpm dlx shadcn@latest add @paneui/tabs

Usage

Composition

Examples

Controlled

Use when the URL or other UI decides which tab is open.

Disabled

Full Width

Vertical

Use for settings pages with many sections.

Icon Only

Sizes

Match the toolbar the tabs sit in.

Underline

Use for page-level sections, where a filled track would compete with the content.

RTL

Motion

The indicator slides over 300ms ease-out. Under prefers-reduced-motion: reduce it jumps without sliding.

Keyboard

ArrowLeft / ArrowRight (or ArrowUp / ArrowDown when vertical) move focus between tabs (looping), Home / End jump to the ends, and Enter or Space activates the focused tab.

API Reference

Built on the Tabs primitive. Only the props this library adds or changes are listed; everything else passes through.

Tabs

Column wrapper with a 12px gap between list and panels; a row when vertical. Also accepts every prop of Tabs.Root.

defaultValue= 0
any
Tab selected on first render.
value
any
Controlled selected tab.
orientation= "horizontal"
"horizontal" | "vertical"
Lays the list out as a row or a column; the indicator and arrow keys follow it.
onValueChange
(value: any, eventDetails) => void
Called when the selected tab changes.
PropTypeDefaultDescription
defaultValueany0Tab selected on first render.
valueany—Controlled selected tab.
orientation"horizontal" | "vertical""horizontal"Lays the list out as a row or a column; the indicator and arrow keys follow it.
onValueChange(value: any, eventDetails) => void—Called when the selected tab changes.

TabsList

Segmented track. Renders the sliding indicator after its children. Also accepts every prop of Tabs.List.

size= "default"
"xs" | "sm" | "default" | "lg"
Height 24 / 28 / 32 / 36px for the list, the Button heights. Applies to every tab.
variant= "default"
"default" | "underline"
default is a raised indicator on a well; underline is a 2px bar on a hairline.
activateOnFocus= false
boolean
Select a tab as soon as it receives keyboard focus.
loopFocus= true
boolean
Wrap arrow-key focus at the ends.
PropTypeDefaultDescription
size"xs" | "sm" | "default" | "lg""default"Height 24 / 28 / 32 / 36px for the list, the Button heights. Applies to every tab.
variant"default" | "underline""default"default is a raised indicator on a well; underline is a 2px bar on a hairline.
activateOnFocusbooleanfalseSelect a tab as soon as it receives keyboard focus.
loopFocusbooleantrueWrap arrow-key focus at the ends.
data-size
The size value.
data-variant
The variant value.
Data attributeDescription
data-sizeThe size value.
data-variantThe variant value.

TabsTab

Sizes its icons to 16px. Also accepts every prop of Tabs.Tab.

value*
any
Matches the TabsPanel it shows.
disabled= false
boolean
Dim the tab, block selection and skip it in the keyboard order.
PropTypeDefaultDescription
value*any—Matches the TabsPanel it shows.
disabledbooleanfalseDim the tab, block selection and skip it in the keyboard order.
data-active
Present on the selected tab.
data-disabled
Present when disabled.
data-orientation
horizontal or vertical, from the root.
Data attributeDescription
data-activePresent on the selected tab.
data-disabledPresent when disabled.
data-orientationhorizontal or vertical, from the root.

TabsPanel

Also accepts every prop of Tabs.Panel.

value*
any
The TabsTab value that shows this panel.
keepMounted= false
boolean
Keep the panel in the DOM while hidden.
typeset= false
boolean | "docs" | "reading" | "chat"
Turn prose styles back on for the panel content inside a typeset container, or name a preset when it stands alone.
PropTypeDefaultDescription
value*any—The TabsTab value that shows this panel.
keepMountedbooleanfalseKeep the panel in the DOM while hidden.
typesetboolean | "docs" | "reading" | "chat"falseTurn prose styles back on for the panel content inside a typeset container, or name a preset when it stands alone.