Bonsai Design System

Tabs

Tabbed navigation with two variants — animated underline (line) and container pills (solid).

Preview

Overview content goes here.

Variants

TabsList accepts a variant prop with two values:

  • "line" (default) — Underline indicator that slides between triggers using a MutationObserver + ResizeObserver. Use for primary, page-level tab strips.
  • "solid" — Pill triggers inside a tinted, bordered container; the active trigger fills with the page background. Use for nested / second-level tab strips, so they read as visually distinct from the outer line tabs.

Solid (nested) variant

Vessels list goes here.

Pairing line + solid

The two variants are designed to compose: page-level tabs use line, the nested tab strip inside one of those tabs uses solid. The user instantly sees the second level is a sub-navigation, not a peer.

<Tabs defaultValue="catalog">
  <TabsList>
    {/* primary nav — line variant (default) */}
    <TabsTrigger value="catalog">Catalog</TabsTrigger>
    <TabsTrigger value="settings">Settings</TabsTrigger>
  </TabsList>

  <TabsContent value="catalog">
    <Tabs defaultValue="vessels">
      <TabsList variant="solid" className="w-fit">
        {/* secondary nav — solid variant */}
        <TabsTrigger value="vessels">Vessels</TabsTrigger>
        <TabsTrigger value="ports">Ports</TabsTrigger>
      </TabsList>
      {/* … */}
    </Tabs>
  </TabsContent>
</Tabs>

Props

TabsList

Prop

Type

Tabs (Radix Root)

Prop

Type

Usage

import { Tabs, TabsList, TabsTrigger, TabsContent } from "@/components/ui/tabs"

<Tabs defaultValue="tab1">
  <TabsList>
    <TabsTrigger value="tab1">Tab 1</TabsTrigger>
    <TabsTrigger value="tab2">Tab 2</TabsTrigger>
  </TabsList>
  <TabsContent value="tab1">Content 1</TabsContent>
  <TabsContent value="tab2">Content 2</TabsContent>
</Tabs>

Install

npx shadcn add @bonsai/tabs

On this page