Phoundry UI

Tabs

Tab bar with keyboard navigation, closable tabs, and three visual variants (default, pills, underline). Supports horizontal/vertical orientation and panel rendering via snippets.

import { Tabs } from 'phoundry-ui';

Default Variant

Active: general

Show code
<Tabs
  items={tabs}
  value={active}
  onchange={(id) => active = id}
/>

Pills Variant

Active: general

Show code
<Tabs
  items={tabs}
  value={active}
  onchange={(id) => active = id}
  variant="pills"
/>

Vertical tab list

orientation="vertical" stacks tabs and pins the panel beside/below depending on your layout wrapper- Combine with variant="pills" for sidebar navigation.

Vertical orientation keeps the tablist beside the panel - active: General
Show code
<Tabs items={tabs} value={active} onchange={set} orientation="vertical" variant="pills" />

Underline Variant

Active: general

Show code
<Tabs
  items={tabs}
  value={active}
  onchange={(id) => active = id}
  variant="underline"
/>

Panel without View Transitions

Disable cross-fading when the DOM inside panels cannot be duplicated safely or when animations feel sluggish on low-power devices.

Static swap (no view transition)- Editor
Show code
<Tabs items={tabs} value={active} onchange={set} viewTransition={false}>
  {#snippet panel(item)}…{/snippet}
</Tabs>

With Panel Content

Content for Editor tab.
Show code
<Tabs
  items={closableTabs}
  value={active}
  onchange={(id) => active = id}
  onclose={(id) => removeTab(id)}
>
  {#snippet panel(item)}
    <div class="p-4">Content for {item.label}</div>
  {/snippet}
</Tabs>

Props

PropTypeDefaultDescription
items requiredTabItem[]-Array of tab definitions.
value requiredstring-Active tab id.
onchange required(id: string) => void-Called when active tab changes.
onclose (id: string) => void-Called when a closable tab is closed.
orientation 'horizontal' | 'vertical''horizontal'Tab list direction.
variant 'default' | 'pills' | 'underline''default'Visual style.
size 'sm' | 'md''sm'Tab trigger height aligned to Button `sm` (h-5.5) / `md` (h-7).
viewTransition booleantrueUse the View Transition API to cross-fade panel content on tab change (where supported).
class string-Additional CSS classes on the tab list.
tab Snippet<[TabItem, boolean]>-Custom tab renderer snippet.
panel Snippet<[TabItem]>-Panel content rendered below the active tab.

TabItem

PropTypeDefaultDescription
id requiredstring-Unique tab identifier.
label requiredstring-Tab display text.
icon string-Iconify icon string.
closable booleanfalseShow close button on tab.
disabled booleanfalseDisable tab interaction.

Usage tips

  • Arrow keys navigate between tabs; Home/End jump to first/last.
  • Use variant="underline" for content-area tab bars and "pills" for sidebar navigation.
  • The panel snippet receives the active TabItem - render different content per tab inside it.
  • Provide onclose to enable the close button on tabs marked closable: true.
  • Panel content has built-in top padding and cross-fades via the View Transition API. Pass viewTransition={false} to opt out.