Skip to content
Components

Tabs

Tabbed content switcher (Base UI Tabs) that composes TabsList / TabsTrigger / TabsContent. Provides shared variant/size/fullWidth through context so the parts stay in sync, and tracks the active value to drive the sliding TabsIndicator. Controlled via value/onValueChange, uncontrolled via defaultValue.

Dimensions
200 × 200 × 10 mm
Wear rating
PEI III
Finish
Matte glaze

Usage

@instruments/materia-ui/components/tabs

<Tabs className="w-96" defaultValue="specs">
  <TabsList>
    <TabsTrigger value="overview">Overview</TabsTrigger>
    <TabsTrigger value="specs">Specs</TabsTrigger>
    <TabsTrigger value="suppliers">Suppliers</TabsTrigger>
  </TabsList>
  <TabsContent className="mt-4" value="overview">
    <Text size="paragraph-sm" variant="muted">
      Glazed terracotta hex with a matte, hand-finished surface - a warm,
      tactile field tile for feature walls and splashbacks.
    </Text>
  </TabsContent>
  <TabsContent className="mt-4" value="specs">
    <DescriptionList>
      <DescriptionItem>
        <DescriptionTerm>Dimensions</DescriptionTerm>
        <DescriptionDetails>200 × 200 × 10 mm</DescriptionDetails>
      </DescriptionItem>
      <DescriptionItem>
        <DescriptionTerm>Wear rating</DescriptionTerm>
        <DescriptionDetails>PEI III</DescriptionDetails>
      </DescriptionItem>
      <DescriptionItem>
        <DescriptionTerm>Finish</DescriptionTerm>
        <DescriptionDetails>Matte glaze</DescriptionDetails>
      </DescriptionItem>
    </DescriptionList>
  </TabsContent>
  <TabsContent className="mt-4" value="suppliers">
    <Stack gap="xs">
      <Text size="paragraph-sm">Veneto Ceramiche · Italy</Text>
      <Text size="paragraph-sm">Clayworks London · United Kingdom</Text>
      <Text size="paragraph-sm">Terra Studio · Portugal</Text>
    </Stack>
  </TabsContent>
</Tabs>

Best practices

  • Reach for Tabs to swap in-page panels via TabsContent; when each tab is a route, use TabNavigation instead (renders links, no panels).

  • Compose TabsList/TabsTrigger/TabsContent - shared variant/size/fullWidth flow through context, so set them on Tabs, not each trigger.

Props

Tabs

PropTypeDefaultDescription
classNamestring
valuestring | null

Selected tab (controlled). null means no tab is active.

defaultValuestring | null

Initially selected tab (uncontrolled). Defaults to the first enabled tab.

onValueChange(value: string | null, eventDetails: TabsPrimitive.Root.ChangeEventDetails) => void

Fires with the newly selected tab value, or null when none is available.

variant"line" | "pill""pill"

Indicator style: "pill" (filled capsule) or "line" (underline).

sizeResponsiveSize"base"

Trigger sizing on the shared component-size scale - a single token or a per-breakpoint object like { base: "sm", md: "lg" }.

fullWidthboolean

When true, tabs fill container width with equal proportional widths

TabsContent

PropTypeDefaultDescription
classNamestring

TabsList

PropTypeDefaultDescription
classNamestring
variant"line" | "pill" | null | undefined
size"base" | "2xs" | "xs" | "sm" | "lg" | "xl" | "2xl" | "3xl" | null | undefined

TabsPanel

PropTypeDefaultDescription
children(required)import("react").ReactNode
classNamestring
layoutboolean | "position" | "size" | "preserve-aspect"

TabsTrigger

PropTypeDefaultDescription
variant"line" | "pill" | null | undefined
size"base" | "2xs" | "xs" | "sm" | "lg" | "xl" | "2xl" | "3xl" | null | undefined
classNamestring
countnumber

Optional count to display alongside the tab label

dotstring

Dot colour indicator (CSS colour value)

iconIconComponent | undefined

Leading/trailing icon, rendered through Icon.

iconPlacement"end" | "start"

Which side the icon sits on. Requires icon. Defaults to "start".

Also exports

  • consttabsAnatomy

Anatomy

Tabs

tabs

Tabbed content switcher

TabsList

tabs-list

Container for tab triggers

TabsTrigger

tabs-trigger

Button to switch tab content

TabsContent

tabs-content

Content panel for each tab

Composition