Components / Controls
Tabs
Pill or underline tabs. A panel is not mounted until its tab is opened.
Install — needs @hiip registered in components.json
bunx shadcn@latest add @hiip/tabsOr by URL, with the token in the query
bunx shadcn@latest add "https://ui.hiip.ai/r/tabs.json?token=$HIIP_REGISTRY_TOKEN"Both need a token — set one up.
Anatomy
Import from components/ui/hiip-ui/tabs.
<Tabs defaultSelectedKey="board">
<TabsList variant="pill"> {/* or "line" */}
<TabsTrigger id="board" icon={…} count={12}>Board</TabsTrigger>
<TabsTrigger id="table">Table</TabsTrigger>
</TabsList>
{/* Only the open panel is mounted — `keepMounted` opts one out. */}
<TabsContent id="board">…</TabsContent>
<TabsContent id="table" keepMounted>…</TabsContent>
</Tabs>Examples
function TabsDemo() {
return (
<div className="flex w-full flex-col gap-8">
{/* The pill: a control inside a toolbar, switching a view of one thing. */}
<Tabs defaultSelectedKey="board" className="gap-3">
<TabsList className="self-center">
<TabsTrigger id="board" icon={DashboardSquare01Icon}>
Board
</TabsTrigger>
<TabsTrigger id="table" icon={Menu01Icon}>
Table
</TabsTrigger>
</TabsList>
<TabsContent id="board" className={PANEL}>
Cards, grouped by column
</TabsContent>
<TabsContent id="table" className={PANEL}>
Rows, sorted by date
</TabsContent>
</Tabs>
{/* The underline: page-level sections, with a count on each. Wide enough
to overflow on a phone, so the list scrolls rather than widening the
page. */}
<Tabs defaultSelectedKey="created" className="gap-3">
<div className="max-w-full overflow-x-auto">
<TabsList variant="line" className="w-max">
{SHIPPING.map((s) => (
<TabsTrigger
key={s.value}
id={s.value}
icon={s.icon}
tone={s.tone}
count={s.count}
>
{s.label}
</TabsTrigger>
))}
</TabsList>
</div>
{SHIPPING.map((s) => (
<TabsContent key={s.value} id={s.value} className={PANEL}>
{s.count} {s.count === 1 ? "order" : "orders"} — {s.label}
</TabsContent>
))}
</Tabs>
</div>
);
}API Reference
Generated from the source. Props forwarded to the underlying element are not listed.
Tabs
Groups a list with its panels and owns which one is active.
| Prop | Type | Default |
|---|---|---|
className | string | undefined | — |
defaultSelectedKeyThe tab active on mount. | string | undefined | — |
onSelectionChangeFires for a click or an arrow key — and once on mount when the root is uncontrolled and `defaultSelectedKey` names no mounted tab, reporting the tab that was… | ((key: string) => void) | undefined | — |
orientationThe component orientation (layout flow direction). | Orientation | undefined | — |
renderAllows you to replace the component's HTML element with a different tag, or compose it with another component. | ReactElement<unknown, string | JSXElementConstructor<any>> | ComponentRenderFn<HTMLProps, TabsRootState> | undefined | — |
selectedKeyThe active tab's `id`. | string | undefined | — |
styleStyle applied to the element, or a function that returns a style object based on the component's state. | CSSProperties | ((state: TabsRootState) => CSSProperties | undefined) | undefined | — |
TabsList
The row of triggers, and the indicator that travels between them.
| Prop | Type | Default |
|---|---|---|
activateOnFocusWhether to automatically change the active tab on arrow key focus. | boolean | undefined | — |
className | string | undefined | — |
loopFocusWhether to loop keyboard focus back to the first item when the end of the list is reached while using the arrow keys. | boolean | undefined | — |
renderAllows you to replace the component's HTML element with a different tag, or compose it with another component. | ReactElement<unknown, string | JSXElementConstructor<any>> | ComponentRenderFn<HTMLProps, TabsListState> | undefined | — |
styleStyle applied to the element, or a function that returns a style object based on the component's state. | CSSProperties | ((state: TabsListState) => CSSProperties | undefined) | undefined | — |
variant`pill` is a control in a toolbar; `line` is page-level navigation. | TabsVariant | undefined | "pill" |
TabsTrigger
One trigger.
| Prop | Type | Default |
|---|---|---|
idrequiredThis tab's key, matched against the `TabsContent` carrying the same one. | string | — |
className | string | undefined | — |
countShown as a badge after the label. | number | undefined | — |
disabledWhether the Tab is disabled. | boolean | undefined | — |
icon | IconSvgElement | undefined | — |
nativeButtonWhether the component renders a native `<button>` element when replacing it via the `render` prop. | boolean | undefined | — |
renderAllows you to replace the component's HTML element with a different tag, or compose it with another component. | ReactElement<unknown, string | JSXElementConstructor<any>> | ComponentRenderFn<HTMLProps, TabsTabState> | undefined | — |
styleStyle applied to the element, or a function that returns a style object based on the component's state. | CSSProperties | ((state: TabsTabState) => CSSProperties | undefined) | undefined | — |
toneColours the ICON only — the label stays on the trigger's own colour. | "default" | "info" | "success" | "warning" | "danger" | undefined | — |
TabsContent
The panel for the trigger of the same `id`.
| Prop | Type | Default |
|---|---|---|
idrequiredThe `id` of the trigger that opens this panel. | string | — |
className | string | undefined | — |
keepMountedWhether to keep the HTML element in the DOM while the panel is hidden. | boolean | undefined | — |
renderAllows you to replace the component's HTML element with a different tag, or compose it with another component. | ReactElement<unknown, string | JSXElementConstructor<any>> | ComponentRenderFn<HTMLProps, TabsPanelState> | undefined | — |
styleStyle applied to the element, or a function that returns a style object based on the component's state. | CSSProperties | ((state: TabsPanelState) => CSSProperties | undefined) | undefined | — |
- Type
registry:ui- npm packages
@base-ui/react @hugeicons/react- Files written
- components/ui/hiip-ui/tabs.tsx