Component guideEditable source

Tabs

Related panels with one active tab at a time.

Original component docs
On this page4 sectionsBack to top

Use Tabs to switch between closely related views without navigating to a new page. Match trigger values to TabsContent values. Use links for independently navigable destinations.

Live preview
Loading preview...

#Installation

Complete the base setup. For manual installation:

npx shadcn@latest add https://neobrutal-ui.andongmin.com/r/tabs.json

The live preview's forms additionally use Button, Card, Input, and Label. Install them before copying the Code example:

npx shadcn@latest add https://neobrutal-ui.andongmin.com/r/button.json https://neobrutal-ui.andongmin.com/r/card.json https://neobrutal-ui.andongmin.com/r/input.json https://neobrutal-ui.andongmin.com/r/label.json

#Usage

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

export default function ProjectTabs() {
  return (
    <Tabs defaultValue="overview" className="w-full max-w-md">
      <TabsList aria-label="Project views">
        <TabsTrigger value="overview">Overview</TabsTrigger>
        <TabsTrigger value="activity">Activity</TabsTrigger>
      </TabsList>
      <TabsContent value="overview">Project summary and current goals.</TabsContent>
      <TabsContent value="activity">No recent activity.</TabsContent>
    </Tabs>
  );
}

#API reference

Prop / partPurposeDefault
Tabs.value / onValueChangeControlled active panelUncontrolled
Tabs.defaultValueInitial panel; specify a matching trigger valueBase UI default
Tabs.orientationHorizontal or vertical navigationhorizontal
TabsList.activateOnFocusActivate with arrow-key focus; false requires Enter or Spacetrue
TabsList.loopFocusWrap focus at the endstrue
TabsList.variantdefault or line stylingdefault
TabsTrigger.value / TabsContent.valueMatching panel identifierRequired
TabsTrigger.disabledUnavailable tabfalse
TabsContent.keepMountedRetain an inactive panel in the DOMfalse

Each part accepts a string or state-based className function. For example, TabsTrigger exposes active and disabled, while TabsContent exposes hidden.

Tabs delegates selection, keyboard navigation, refs, and rendering to Base UI. Use its render prop for element composition and activateOnFocus for manual activation; no second state or keyboard implementation is maintained.

#Accessibility

Name the tab list. Keep labels short and test arrows, Home/End, and Tab into the panel. Set activateOnFocus={false} on TabsList when opening a panel triggers expensive work. Do not hide critical instructions behind an undiscoverable tab.