Tabs

A tabbed interface component for organizing content into separate panels with line-style navigation.

Usage

Basic Tabs

import { Tabs, TabsList, TabsTrigger, TabsContent } from "@prisma-docs/eclipse";

export function BasicTabs() {
  return (
    <Tabs defaultValue="account">
      <TabsList>
        <TabsTrigger value="account">Account</TabsTrigger>
        <TabsTrigger value="password">Password</TabsTrigger>
      </TabsList>
      <TabsContent value="account">
        Account settings content
      </TabsContent>
      <TabsContent value="password">
        Password settings content
      </TabsContent>
    </Tabs>
  );
}

Live Example:

Account settings content

Password settings content

Controlled Tabs

You can control the active tab programmatically:

import { Tabs, TabsList, TabsTrigger, TabsContent } from "@prisma-docs/eclipse";
import { useState } from "react";

export function ControlledTabs() {
  const [activeTab, setActiveTab] = useState("tab1");

  return (
    <>
      <button onClick={() => setActiveTab("tab2")}>
        Switch to Tab 2
      </button>
      
      <Tabs value={activeTab} onValueChange={setActiveTab}>
        <TabsList>
          <TabsTrigger value="tab1">Tab 1</TabsTrigger>
          <TabsTrigger value="tab2">Tab 2</TabsTrigger>
          <TabsTrigger value="tab3">Tab 3</TabsTrigger>
        </TabsList>
        <TabsContent value="tab1">Content 1</TabsContent>
        <TabsContent value="tab2">Content 2</TabsContent>
        <TabsContent value="tab3">Content 3</TabsContent>
      </Tabs>
    </>
  );
}

With Disabled Tabs

import { Tabs, TabsList, TabsTrigger, TabsContent } from "@prisma-docs/eclipse";

export function DisabledTabs() {
  return (
    <Tabs defaultValue="available">
      <TabsList>
        <TabsTrigger value="available">Available</TabsTrigger>
        <TabsTrigger value="locked" disabled>Locked</TabsTrigger>
        <TabsTrigger value="premium" disabled>Premium</TabsTrigger>
      </TabsList>
      <TabsContent value="available">
        This content is available to all users.
      </TabsContent>
      <TabsContent value="locked">
        This content is locked.
      </TabsContent>
      <TabsContent value="premium">
        This content requires a premium subscription.
      </TabsContent>
    </Tabs>
  );
}

Live Example:

This content is available to all users.

This content is locked.

This content requires a premium subscription.

Colored Tabs

Use the color prop on the Tabs component to apply brand-specific colors to all tab triggers:

import { Tabs, TabsList, TabsTrigger, TabsContent } from "@prisma-docs/eclipse";

export function ColoredTabs() {
  return (
    <Tabs defaultValue="orm" color="orm">
      <TabsList>
        <TabsTrigger value="orm">Prisma ORM</TabsTrigger>
        <TabsTrigger value="migrate">Migrate</TabsTrigger>
        <TabsTrigger value="studio">Studio</TabsTrigger>
      </TabsList>
      <TabsContent value="orm">
        Content about Prisma ORM
      </TabsContent>
      <TabsContent value="migrate">
        Content about Prisma Migrate
      </TabsContent>
      <TabsContent value="studio">
        Content about Prisma Studio
      </TabsContent>
    </Tabs>
  );
}

You can also override the color on individual triggers if needed:

<Tabs defaultValue="orm" color="orm">
  <TabsList>
    <TabsTrigger value="orm">Prisma ORM</TabsTrigger>
    <TabsTrigger value="ppg" color="ppg">Prisma Postgres</TabsTrigger>
  </TabsList>
  {/* Content */}
</Tabs>

Live Example:

Prisma ORM

Next-generation ORM for Node.js and TypeScript.

Prisma Migrate

Declarative data modeling and schema migrations.

Prisma Studio

Visual database browser and editor.

API Reference

Tabs

The root tabs container component.

Props:

  • defaultValue - The default active tab (string, optional)
  • value - The controlled active tab value (string, optional)
  • onValueChange - Callback when active tab changes ((value: string) => void, optional)
  • color - Color variant for all tab triggers: "default", "orm", or "ppg" (default: "default")
  • orientation - Tab orientation: "horizontal" or "vertical" (default: "horizontal")
  • dir - Text direction: "ltr" or "rtl" (optional)
  • activationMode - How tabs are activated: "automatic" or "manual" (default: "automatic")
  • className - Additional CSS classes (optional)

TabsList

The container for tab triggers with an underline indicator.

Props:

  • className - Additional CSS classes (optional)
  • All standard HTML <div> attributes

TabsTrigger

Individual tab button/trigger.

Props:

  • value - The unique value for this tab (string, required)
  • color - Color variant override for this specific trigger: "default", "orm", or "ppg" (optional, inherits from Tabs if not set)
  • disabled - Whether the tab is disabled (boolean, default: false)
  • className - Additional CSS classes (optional)
  • All standard HTML <button> attributes

TabsContent

The content panel for a tab.

Props:

  • value - The tab value this content corresponds to (string, required)
  • forceMount - Force content to always be mounted (boolean, optional)
  • className - Additional CSS classes (optional)
  • All standard HTML <div> attributes

Features

  • ✅ Clean underline indicator design (line variant)
  • ✅ Smooth transitions and animations
  • ✅ Keyboard navigation support
  • ✅ Controlled and uncontrolled modes
  • ✅ Disabled tab support
  • ✅ Horizontal and vertical orientations
  • ✅ Brand color variants (ORM, Postgres, Default)
  • ✅ Accessible with ARIA attributes
  • ✅ Eclipse design system styling
  • ✅ Built on Radix UI primitives

Best Practices

  • Use tabs for organizing related content into separate views
  • Provide clear, concise labels for each tab
  • Keep the number of tabs reasonable (3-7 tabs maximum)
  • Use defaultValue to set a sensible default active tab
  • Don't nest tabs within tabs - use a different pattern instead
  • Ensure tab content is meaningful and substantial
  • Use disabled state sparingly and provide context when tabs are disabled
  • Consider using a different pattern for large amounts of navigation
  • Place tabs near the content they control
  • Maintain consistent tab ordering across similar interfaces

Keyboard Navigation

The Tabs component supports full keyboard navigation:

KeyAction
TabMove focus to the active tab or into tab content
ArrowLeft / ArrowRightNavigate between tabs (horizontal)
ArrowUp / ArrowDownNavigate between tabs (vertical)
HomeMove to first tab
EndMove to last tab
Enter / SpaceActivate focused tab (in manual mode)

Accessibility

  • Uses proper ARIA roles (tablist, tab, tabpanel)
  • Active tab is indicated with aria-selected="true"
  • Tab panels are associated with their triggers via aria-controls and aria-labelledby
  • Keyboard navigation follows ARIA authoring practices
  • Disabled tabs are properly marked and not focusable
  • Screen readers announce tab states and content

Common Use Cases

Settings Panels

<Tabs defaultValue="profile">
  <TabsList>
    <TabsTrigger value="profile">Profile</TabsTrigger>
    <TabsTrigger value="account">Account</TabsTrigger>
    <TabsTrigger value="notifications">Notifications</TabsTrigger>
  </TabsList>
  {/* Content for each tab */}
</Tabs>

Documentation Examples

<Tabs defaultValue="preview">
  <TabsList>
    <TabsTrigger value="preview">Preview</TabsTrigger>
    <TabsTrigger value="code">Code</TabsTrigger>
  </TabsList>
  {/* Preview and code content */}
</Tabs>

Feature Comparison

<Tabs defaultValue="features">
  <TabsList>
    <TabsTrigger value="features">Features</TabsTrigger>
    <TabsTrigger value="pricing">Pricing</TabsTrigger>
    <TabsTrigger value="faq">FAQ</TabsTrigger>
  </TabsList>
  {/* Comparison content */}
</Tabs>

Dashboard Views

<Tabs defaultValue="overview">
  <TabsList>
    <TabsTrigger value="overview">Overview</TabsTrigger>
    <TabsTrigger value="analytics">Analytics</TabsTrigger>
    <TabsTrigger value="reports">Reports</TabsTrigger>
  </TabsList>
  {/* Dashboard content */}
</Tabs>

Integration with Fumadocs

You can use Tabs in your documentation pages for code examples:

import { Tabs, TabsList, TabsTrigger, TabsContent } from "@prisma-docs/eclipse";

export default function Page() {
  return (
    <article>
      <h1>API Documentation</h1>
      
      <Tabs defaultValue="curl">
        <TabsList>
          <TabsTrigger value="curl">cURL</TabsTrigger>
          <TabsTrigger value="javascript">JavaScript</TabsTrigger>
          <TabsTrigger value="python">Python</TabsTrigger>
        </TabsList>
        <TabsContent value="curl">
          <pre><code>curl https://api.example.com/data</code></pre>
        </TabsContent>
        <TabsContent value="javascript">
          <pre><code>fetch('https://api.example.com/data')</code></pre>
        </TabsContent>
        <TabsContent value="python">
          <pre><code>requests.get('https://api.example.com/data')</code></pre>
        </TabsContent>
      </Tabs>
    </article>
  );
}

On this page