What is Tabs?

Tabs: Tabs are a row of labeled triggers that switch between panels of content in the same place, showing one panel at a time without leaving the page.

Tabs divide related content into sections that share one area of the page. A list of labels sits above (or beside) a panel, the selected label is highlighted and connected to its panel, and choosing another label swaps the content. Settings pages, detail views with Overview, Activity and Files, code samples in several languages, and product pages with Description, Specs and Reviews all use them. Tabs promise that the sections are peers: same level, any order, one visible at a time.

When to use it

  • Three to about seven sections of equal importance that people switch between, where stacking all of them would make a long page.
  • Content that does not need comparing. If users must look at two sections together, stack them instead.
  • Not for steps in order, which is a stepper, and not for pages with their own URLs, which should be links styled as tabs inside a nav.
  • Not for one or two sections. A single tab is a heading; two short sections can just be two sections.
  • For switching a value or a view mode rather than content panels, a segmented control reads better.

Accessibility

The WAI-ARIA tabs pattern has three roles. The container of labels is role="tablist", each label is role="tab" with aria-selected and aria-controls pointing at its panel, and each panel is role="tabpanel" with aria-labelledby pointing back at its tab. The tab list is one Tab stop with a roving tabindex: Left and Right Arrow (Up and Down when aria-orientation="vertical") move between tabs, Home and End jump to the ends, and Tab moves from the selected tab into its panel.

There are two activation modes. Automatic activation selects a tab as soon as it receives focus, which is right when panels are cheap to show. Manual activation moves focus only and waits for Enter or Space, which is better when switching loads data or is otherwise slow. Keep the selected tab in the URL hash or a query parameter when people might share or reload a tab.

How to build one in React

MiniDev's Tabs are built on the Base UI tabs, which provide the roles and keyboard model. The active tab carries a raised thumb, or a 2px underline with variant="line", that glides between tabs:

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

export function ProjectTabs() {
  return (
    <Tabs defaultValue="overview">
      <TabsList variant="line">
        <TabsTrigger value="overview">Overview</TabsTrigger>
        <TabsTrigger value="activity">Activity</TabsTrigger>
        <TabsTrigger value="files">Files</TabsTrigger>
      </TabsList>
      <TabsContent value="overview">Summary, owners and status.</TabsContent>
      <TabsContent value="activity">Recent changes.</TabsContent>
      <TabsContent value="files">Attachments.</TabsContent>
    </Tabs>
  )
}

Pass value and onValueChange to control the selection, and orientation="vertical" for a side-by-side layout like VerticalTabs. Make tab labels short nouns, keep their order stable, and avoid putting a count badge on more than one or two of them. The SettingsLayout block shows tabs used for a full settings area; more navigation patterns are in the navigation category.

TabsuiTabs on Base UI with a raised thumb or a line underline that springs to the active tab, optional count badges, vertical orientation and roving keyboard focus.npx shadcn@latest add @minidev/tabsVertical TabsuiVertical tabs with a 180px tab list on the left and the active panel on the right, using tab and tabpanel roles. Stacks on mobile. Built for settings screens.npx shadcn@latest add @minidev/vertical-tabs