Elements

Components / Base

Tabs

A set of layered sections of content — built on Base UI — where only one panel is visible at a time. Use them to group related views without leaving the page.

Installation

bash
npx shadcn add https://raw.githubusercontent.com/levi-putna/elements/main/registry/tabs/registry.json

Basic

Horizontal tabs
Building overview and key details.
tsx
import { Tabs, TabsList, TabsTrigger, TabsContent } from "@/components/ui/tabs"

<Tabs defaultValue="overview" className="w-full max-w-md">
  <TabsList>
    <TabsTrigger value="overview">Overview</TabsTrigger>
    <TabsTrigger value="levies">Levies</TabsTrigger>
    <TabsTrigger value="documents">Documents</TabsTrigger>
  </TabsList>
  <TabsContent value="overview">Building overview and key details.</TabsContent>
  <TabsContent value="levies">Levy notices and payment status.</TabsContent>
  <TabsContent value="documents">By-laws, minutes and reports.</TabsContent>
</Tabs>

Vertical

Set orientation="vertical" to run the tab list down the side — handy for settings panes and wider layouts.

Vertical tabs
Building overview and key details.
tsx
{/* orientation="vertical" stacks the list down the side */}
<Tabs defaultValue="overview" orientation="vertical">
  <TabsList>
    <TabsTrigger value="overview">Overview</TabsTrigger>
    <TabsTrigger value="levies">Levies</TabsTrigger>
    <TabsTrigger value="documents">Documents</TabsTrigger>
  </TabsList>
  <TabsContent value="overview">Building overview and key details.</TabsContent>
  <TabsContent value="levies">Levy notices and payment status.</TabsContent>
  <TabsContent value="documents">By-laws, minutes and reports.</TabsContent>
</Tabs>

Disabled

Add disabled to a trigger to dim it and skip it during keyboard navigation.

Disabled tab
Building overview and key details.
tsx
{/* disabled tabs are dimmed and skipped by keyboard navigation */}
<Tabs defaultValue="overview" className="w-full max-w-md">
  <TabsList>
    <TabsTrigger value="overview">Overview</TabsTrigger>
    <TabsTrigger value="levies">Levies</TabsTrigger>
    <TabsTrigger value="documents" disabled>Documents</TabsTrigger>
  </TabsList>
  <TabsContent value="overview">Building overview and key details.</TabsContent>
  <TabsContent value="levies">Levy notices and payment status.</TabsContent>
</Tabs>

Icons

Place a Lucide icon inside a trigger; it inherits the label colour and is sized to match the text.

Tabs with icons
Building overview and key details.
tsx
import { Building2, FileText, Users } from "lucide-react"

{/* drop an icon inside the trigger — it's sized automatically */}
<Tabs defaultValue="overview" className="w-full max-w-md">
  <TabsList>
    <TabsTrigger value="overview">
      <Building2 /> Overview
    </TabsTrigger>
    <TabsTrigger value="owners">
      <Users /> Owners
    </TabsTrigger>
    <TabsTrigger value="documents">
      <FileText /> Documents
    </TabsTrigger>
  </TabsList>
  <TabsContent value="overview">Building overview and key details.</TabsContent>
  <TabsContent value="owners">The owners corporation roll.</TabsContent>
  <TabsContent value="documents">By-laws, minutes and reports.</TabsContent>
</Tabs>

Tabs props

PropTypeDefaultDescription
defaultValuestring | number-Uncontrolled value of the tab that is initially active.
valuestring | number-Controlled value of the active tab.
onValueChange(value, event) => void-Fires when the active tab changes.
orientation"horizontal" | "vertical""horizontal"Lays the tab list out as a row or a column.

TabsTrigger props

PropTypeDefaultDescription
valuestring | number-Identifies the tab; must match its TabsContent value.
disabledboolean-Dims the tab and removes it from keyboard navigation.