Tab Strip

Switches, closes and reorders document tabs.

Fix broken chat dragging
Redesign split chats so both panes keep their scroll
Hide empty threads

Installation

pnpm dlx shadcn@latest add @paneui/tab-strip

Usage

Composition

Examples

Pill

Overflow

Reorder

Pass order and onReorder and render children in that order to enable dragging; with reduced motion tabs move instantly. On touch screens a swipe scrolls the strip instead, so dragging is off and tabs and close buttons grow to 32px and 24px targets. Without them the strip is static.

Overflow

Extra tabs scroll sideways and the selected tab is kept in view.

Long titles

A truncated title shows its full text in a hint below the tab after 300ms of hover. The pointer can move into the hint to select and copy the text; pressing the tab closes it. Pass hint to show other text, or hint={false} to turn it off.

Closing

With onClose, tabs show a close button on hover (always on the selected tab), close on middle click, and on ⌫ / Delete when focused. Set closable={false} on a tab to keep it.

Keyboard

The strip is a tablist. ← / → move and select, Home / End jump to the ends, and Enter or Space selects.

API Reference

TabStrip

Also accepts every prop of div.

value
string | null
Selected tab (controlled).
defaultValue
string | null
Initial tab (uncontrolled).
onValueChange
(value: string) => void
Called when a tab is selected.
order
string[]
Tab values in display order; enables drag to reorder with onReorder.
onReorder
(order: string[]) => void
Called with the new order while dragging.
onClose
(value: string) => void
Shows close buttons and handles middle click / Delete.
variant= "default"
"default" | "pill"
Raised card (document tabs on the window band) or fill (panel tabs).
actions
ReactNode
Pinned after the scrolling tabs.
PropTypeDefaultDescription
valuestring | null—Selected tab (controlled).
defaultValuestring | null—Initial tab (uncontrolled).
onValueChange(value: string) => void—Called when a tab is selected.
orderstring[]—Tab values in display order; enables drag to reorder with onReorder.
onReorder(order: string[]) => void—Called with the new order while dragging.
onClose(value: string) => void—Shows close buttons and handles middle click / Delete.
variant"default" | "pill""default"Raised card (document tabs on the window band) or fill (panel tabs).
actionsReactNode—Pinned after the scrolling tabs.

TabStripItem

Also accepts every prop of div.

value*
string
Identifies the tab.
icon
ReactNode
Leading glyph, sized to 14px.
closable
boolean
Override whether this tab shows a close button.
indicator
boolean
Primary dot after the label.
disabled
boolean
Dim and skip the tab.
hint
ReactNode | false
Full text shown on hover while the title is truncated. Defaults to the title; false turns it off.
PropTypeDefaultDescription
value*string—Identifies the tab.
iconReactNode—Leading glyph, sized to 14px.
closableboolean—Override whether this tab shows a close button.
indicatorboolean—Primary dot after the label.
disabledboolean—Dim and skip the tab.
hintReactNode | false—Full text shown on hover while the title is truncated. Defaults to the title; false turns it off.
data-selected
Present on the selected tab.
Data attributeDescription
data-selectedPresent on the selected tab.