ProductBrand
Join us
Foundations
  • Introduction
  • Colors
  • Typography
  • Icons
  • Illustrations
  • Logos
  • Shadows
Components
  • Accordion
  • Alert Dialog
  • Avatar
  • Badge
  • Button
  • Calendar
  • Card
  • Chart
  • Checkbox
  • Collapsible
  • Combobox
  • Context Menu
  • Date Picker
  • Dialog
  • Drawer
  • Dropdown Menu
  • Fluid Avatar
  • Hover Scroll Text
  • Input
  • Kbd
  • Popover
  • Progress Bar
  • Radio Group
  • Scroll Area
  • Select
  • Selectors
  • Separator
  • Separator Dot
  • Shimmer Text
  • Skeleton
  • Slider
  • Switch
  • Tabs
  • Textarea
  • Toast
  • Tooltip
Compositions
  • Empty State
  • File Attachment
  • Floating Bar
  • Input Banner
  • Markdown Editor
  • Media Controls
  • Product Feature Banner
  • Panels
  • Sidebar
  • Reasoning Trace
  • Pagination
  • Data Table
  • Breadcrumb
  • Thread Outline
Inline
  • Overview
  • Stat Tile
  • Metric Row
  • Comparison Table
  • Chart Card
  • Trend Tile
  • Cite
  • Custom
  • Agent skill

Tabs

A set of layered panels where only one panel is displayed at a time, triggered by corresponding tab buttons.

Examples

Portfolio summary with key metrics and recent activity.

Vertical

General

Manage your name, email, and language preferences for the workspace.

Controlled

Content for the first tab.

Overview

Tabs organize content into switchable panels. Three visual variants, three sizes, optional animated indicator, vertical orientation, controlled or uncontrolled state. Built on Base UI Tabs.

tsx
import { Tabs, TabsList, TabsTrigger, TabsContent } from "@rogo-technologies/ui/tabs";

<Tabs defaultValue="account">
  <TabsList variant="primary">
    <TabsTrigger variant="primary" value="account">
      Account
    </TabsTrigger>
    <TabsTrigger variant="primary" value="security">
      Security
    </TabsTrigger>
  </TabsList>
  <TabsContent value="account">Account settings here.</TabsContent>
  <TabsContent value="security">Security settings here.</TabsContent>
</Tabs>;

Usage

Primary

Underline-style tab bar with a bottom border. Active tabs get the brand color border.

tsx
<Tabs defaultValue="account">
  <TabsList variant="primary">
    <TabsTrigger variant="primary" value="account">
      Account
    </TabsTrigger>
    <TabsTrigger variant="primary" value="security">
      Security
    </TabsTrigger>
  </TabsList>
  <TabsContent value="account">…</TabsContent>
</Tabs>

Secondary

Pill-style tabs inside a rounded container. Active tabs get a raised background.

tsx
<TabsList variant="secondary">
  <TabsTrigger variant="secondary" value="all">
    All
  </TabsTrigger>
  <TabsTrigger variant="secondary" value="active">
    Active
  </TabsTrigger>
</TabsList>

Rounded

Like secondary, but each tab is its own fully-rounded pill instead of sitting in a shared track. Inactive tabs carry the grey fill; the active tab goes white and raised. Good for compact, free-standing toggles in toolbars and headers.

tsx
<TabsList variant="rounded">
  <TabsTrigger variant="rounded" value="all">
    All
  </TabsTrigger>
  <TabsTrigger variant="rounded" value="active">
    Active
  </TabsTrigger>
</TabsList>

Sizes

Three sizes are available: sm, md (default), and lg. Set the same size on TabsList and every TabsTrigger so they stay in sync. md matches the original tab styling. Works with all three variants and the animated indicator.

tsx
<TabsList variant="primary" size="sm">
  <TabsTrigger variant="primary" size="sm" value="account">
    Account
  </TabsTrigger>
  <TabsTrigger variant="primary" size="sm" value="security">
    Security
  </TabsTrigger>
</TabsList>

Animated indicator

Pass the same activeLayoutId string to each trigger to get a smooth indicator that slides between tabs via framer-motion layoutId. Works for all three variants: primary slides the underline, secondary and rounded slide the raised pill background.

tsx
<TabsTrigger variant="primary" value="overview" activeLayoutId="settings-tabs">
  Overview
</TabsTrigger>
<TabsTrigger variant="primary" value="analytics" activeLayoutId="settings-tabs">
  Analytics
</TabsTrigger>

Counts

TabsCount renders the count badge that follows a tab label. It reserves 2ch and uses tabular figures, so a count that changes while the tab bar is on screen can't shift the tabs beside it.

tsx
<TabsTrigger variant="primary" value="open" className="gap-1.5">
  Open
  <TabsCount>{openCount}</TabsCount>
</TabsTrigger>

Disabled

tsx
<TabsTrigger variant="primary" value="archive" disabled>
  Archive
</TabsTrigger>

Vertical

For settings sidebars and navigation panels. Use orientation="vertical", lay out the root as a flex row, and override the TabsList / TabsTrigger classes to move the active border from bottom to right.

tsx
<Tabs defaultValue="general" orientation="vertical" className="flex gap-6">
  <TabsList
    variant="primary"
    className="flex-col border-b-0 border-r border-primary h-auto w-40 shrink-0 gap-0"
  >
    <TabsTrigger
      variant="primary"
      value="general"
      className="w-full justify-start border-b-0 border-r-2 px-3 py-1.5"
    >
      General
    </TabsTrigger>
  </TabsList>
  <div className="flex-1">
    <TabsContent value="general" className="mt-0">
      …
    </TabsContent>
  </div>
</Tabs>

Controlled

tsx
const [activeTab, setActiveTab] = useState("tab1");

<Tabs value={activeTab} onValueChange={setActiveTab}>
  <TabsList variant="primary">
    <TabsTrigger variant="primary" value="tab1">
      First
    </TabsTrigger>
    <TabsTrigger variant="primary" value="tab2">
      Second
    </TabsTrigger>
  </TabsList>
  <TabsContent value="tab1">…</TabsContent>
  <TabsContent value="tab2">…</TabsContent>
</Tabs>;

API

Tabs

PropTypeDefaultDescription
valuestring-Controlled active tab value.
defaultValuestring-Uncontrolled initial active tab.
onValueChange(value: string) => void-Callback when the active tab changes.
orientation"horizontal" | "vertical""horizontal"Layout direction.
classNamestring-Additional CSS classes.

TabsList

PropTypeDefaultDescription
variant"primary" | "secondary" | "rounded""primary"Visual style variant.
size"sm" | "md" | "lg""md"Tab sizing scale.
classNamestring-Additional CSS classes.

TabsTrigger

PropTypeDefaultDescription
valuestring-Unique tab identifier (required).
variant"primary" | "secondary" | "rounded""primary"Visual style variant.
size"sm" | "md" | "lg""md"Tab sizing scale. Match the TabsList size.
activeLayoutIdstring-Renders an animated indicator via framer-motion layoutId. Works on all variants.
disabledbooleanfalseDisables the tab.
classNamestring-Additional CSS classes.

TabsCount

Renders a <span>; takes the count as children plus any span props.

PropTypeDefaultDescription
classNamestring-Additional CSS classes.

TabsContent

PropTypeDefaultDescription
valuestring-Value matching a TabsTrigger (required).
keepMountedbooleanfalseKeep DOM element when panel is hidden.
classNamestring-Additional CSS classes.

Guidelines

Do

  • Match variant and size on TabsList and TabsTrigger for consistent styling
  • Use activeLayoutId with the same string on all triggers when you want a sliding indicator
  • Use orientation="vertical" for settings sidebars and navigation panels
  • Keep tab labels short: one or two words

Don't

  • Don't nest tabs inside tabs, since it creates confusing navigation
  • Don't use tabs for sequential steps. Use a stepper or wizard instead
  • Don't use more than 5–6 tabs. Group or collapse content if needed
  • Don't mix variants within the same tab group
PreviousSwitch
NextTextarea
Made in NYC© 2026 Rogo Technologies Inc.

Design at Rogo

We’re redesigning an entire industry. Come design it with us.

See open roles

Design at Rogo

  • How we workThe mission of design at Rogo, and the open roles
  • About RogoThe company and the product