Skip to content

Now in the official shadcn registry directory.

Start free

Tabs

Tabs with 3 list variants (solid segmented, line underline and pill) - triggers pick up the variant automatically.

navigationdisclosure
A free styled version is available
Requests, latency and uptime at a glance.

Installation

Run the following command

npx shadcn@latest add @ai2/tabs

Dependencies, the @ai2/tokens theme and the component file are installed together.

Usage

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

<Tabs defaultValue="overview">
  <TabsList variant="line">
    <TabsTrigger value="overview">Overview</TabsTrigger>
    <TabsTrigger value="settings">Settings</TabsTrigger>
  </TabsList>
  <TabsContent value="overview">Overview content</TabsContent>
  <TabsContent value="settings">Settings content</TabsContent>
</Tabs>

Set variant once on TabsList; every trigger inside inherits it. Each TabsContent pairs with a trigger through its value.

Examples

Solid

1.2M requests this week.

The default segmented style - a raised active tab on a surface-3 track.

Line

Project overview and setup.

A brand-colored underline on the active tab - the docs-page classic.

Pill

12 projects.

Disabled tab

Preview is disabled until the draft compiles.

Sizes

md
Requests, latency and uptime at a glance.
sm
Requests, latency and uptime at a glance.

size sets the list height and trigger text scale. md is the default; sm suits dense toolbars. Like variant, it flows from the list to every trigger via context.

Props

variant and size live on TabsList. All four parts also accept their radix Tabs props - defaultValue, value / onValueChange on the root, value on triggers and content.

TabsList props

PropTypeDefaultDescription
variant"solid" | "line" | "pill""solid"Visual style of the tab list. Triggers inherit the variant from their list via context - no prop needed on TabsTrigger.
size"sm" | "md""md"Scale of the tab list. md is the default height with text-sm; sm shrinks the list and triggers to text-xs for dense toolbars. Triggers inherit the size from their list via context.

ai2 Tabs: three tab styles for React, one variant prop

The ai2 Tabs is a shadcn-compatible tabs component for React, built on the radix-ui Tabs primitive and styled with Tailwind CSS v4. One variant prop on the list switches between three complete looks: a solid segmented control on a raised track, a line style with a brand-colored underline, and a pill style with a filled brand active tab. Triggers read the variant from the list through React context, so you never repeat it per tab.

Because it ships through the shadcn registry format, you install it with one CLI command, an MCP agent, or a copy-paste, and the source lands in your own project. You own the file; there is no runtime dependency on ai2 itself. The live example above is the exact component you get.

What is the ai2 Tabs?

It is a four-part composition: Tabs, TabsList, TabsTrigger and TabsContent. The anatomy matches shadcn/ui exactly, so existing snippets, muscle memory and AI agents keep working without changes; the only additions are the variant and size props on the list.

The root supports controlled and uncontrolled state through radix value, onValueChange and defaultValue, plus full keyboard navigation. Styling comes from the ai2 token file, so all three variants follow your theme in both light and dark mode.

Why use it

  • Accessible by construction: The radix-ui Tabs primitive implements the WAI-ARIA tabs pattern: tablist, tab and tabpanel roles, aria-selected state and focus management come for free.
  • Keyboard activation: Arrow keys move focus between triggers and activate them, Home and End jump to the first and last tab, and disabled triggers are skipped automatically.
  • Three variants, one prop: solid, line and pill cover segmented controls, docs-style underline navigation and filter chips. Set variant once on TabsList; every trigger inherits it via context.
  • Token-driven styling: The solid track uses surface-3, the line and pill actives use the brand token, and the color transition runs on --motion-fast, so tabs match the rest of your theme automatically.
  • Agent-readable metadata: The registry item describes the variant matrix and intended use in plain words, so an MCP agent can find, inspect and install it without guessing.

Features

  • shadcn registry install: One command adds the component, its dependencies and the @ai2/tokens theme to your project.
  • Context-based variant inheritance: TabsList provides the variant through React context and TabsTrigger consumes it, so switching a whole tab set from solid to line is a one-word change.
  • Controlled and uncontrolled state: Use defaultValue for simple cases or drive value and onValueChange from React state to sync tabs with the URL or other UI.
  • Disabled triggers: Any TabsTrigger accepts disabled, which removes it from pointer events and mutes it while keyboard navigation skips it.
  • Focus-visible ring: Triggers show a 3px ring on keyboard focus only, so mouse users get a clean look and keyboard users never lose their place.
  • Data attributes for styling: The list exposes data-slot, data-variant and data-size, and triggers expose data-state, so you can restyle active and inactive tabs from CSS without forking the component.

Production tips

  • Pick the variant by context: Use solid for app-like view switchers, line for page sections and settings screens, and pill for filter rows. Mixing variants on one screen usually reads as noise.
  • Sync tabs with the URL: For page-level tabs, drive value from the router query and update it in onValueChange so deep links and the back button land on the right tab.
  • Keep trigger labels short: Triggers are whitespace-nowrap, so long labels widen the list instead of wrapping. One or two words per tab keeps the row scannable.
  • Do not overload the tab count: Past five or six tabs, users stop scanning. Group related content or switch to a Select for overflow instead of shrinking the labels.
  • Put spacing on TabsContent: The content part is unstyled apart from layout. Add pt-2 or similar per content panel, as the examples on this page do, rather than padding the root.

Works with the rest of ai2

Tabs frame other registry components well. Wrap a tab set in an ai2 Card when the panels need their own surface, add an ai2 Badge inside a trigger for counts like Errors 14, and render an ai2 Table inside a panel for per-tab datasets.

When sections are a list rather than peers, reach for the ai2 Accordion instead, and use the ai2 Toggle Group when the choice changes a setting rather than revealing a panel. Everything shares one token source, so combinations stay visually consistent in both modes.

FAQs

Get new components in your inbox

Component drops, new themes and release notes. No spam, and you can unsubscribe from any email.

© 2026 ai2 design system · MIT licensed · Built with its own components