Tabs
Switch between grouped views with segmented or underline tabs, icon-only triggers, and badge counts on each tab.
import { Tabs } from "@plexui/ui/components/Tabs";Examples
Overview
variant
orientation
size
Segmented with icons
size
Icon only
variant
size
Segmented with badge
size
Underline
size
Underline flush
size
Underline block
size
Underline with icons
size
Underline with badge
size
Vertical segmented
size
Vertical underline
size
Vertical underline with icons
size
Disabled tab
variant
size
Sizing
variant
size
Scrollable
variant
size
Overflow menu
container width
Tabs shares the unified 9-step size scale with Button, Input, Select, and SelectControl.
Migration from SegmentedControl
Tabs replaces and extends SegmentedControl. The old import still works as a backward-compatible alias:
// Old (still works)
import { SegmentedControl } from "@plexui/ui/components/SegmentedControl";
<SegmentedControl.Option value="a">A</SegmentedControl.Option>
// New (recommended)
import { Tabs } from "@plexui/ui/components/Tabs";
<Tabs.Tab value="a">A</Tabs.Tab>Both Tabs.Tab and Tabs.Option are available as sub-components. The SegmentedControl alias defaults to variant="segmented".
API
Tabs (root)
| Prop | Type | Default | Description |
|---|---|---|---|
value | string | — | Selected tab value (controlled, required) |
onChange | (value: string) => void | — | Called when selection changes |
onClick | () => void | — | Called on any click in the group, even when the selection does not change |
variant | "segmented" | "underline" | "segmented" | Visual style: segmented (background highlight) or underline (line indicator) |
orientation | "horizontal" | "vertical" | "horizontal" | Layout direction of the tab group |
size | ControlSize | "md" | Control height (3xs through 3xl) |
gutterSize | "2xs" | "xs" | "sm" | "md" | "lg" | "xl" | — | Horizontal padding of tabs |
pill | boolean | true | Fully rounded control (segmented variant only) |
flush | boolean | false | Text-width indicator, no border, gap spacing (underline variant only) |
block | boolean | false | Full-width control with equal-width tabs |
disabled | boolean | false | Disable all tabs |
aria-label | string | — | Accessible name (required) |
overflow | "scroll" | "menu" | "scroll" | Tabs that do not fit: scroll sideways, or move into a menu at the end (horizontal, not block) |
overflowLabel | string | "More" | Text of the menu button with overflow="menu" |
className | string | — | Extra classes on the group element |
children | ReactNode | — | Tabs.Tab children |
Tabs.Tab
| Prop | Type | Default | Description |
|---|---|---|---|
value | string | — | Tab value (required) |
disabled | boolean | — | Disable this tab |
icon | ReactNode | — | Icon element (sized automatically) |
badge | ReactNode | { content: ReactNode; color?: "secondary" | "success" | "danger" | "warning" | "info" | "discovery" | "caution"; variant?: "soft" | "solid"; pill?: boolean; loading?: boolean } | — | Badge content (for example a count) or a badge config |
aria-label | string | — | Accessible name (required for icon-only tabs) |
children | ReactNode | — | Tab label |
Styling
Tabs reads these component tokens. Override them at any scope to restyle it:
--badge-font-size-2xs: font size 2xs (defaultvar(--font-text-xs-size))--badge-font-size-lg: font size lg (defaultvar(--font-text-sm-size))--badge-font-size-md: font size md (defaultvar(--font-text-sm-size))--badge-font-size-sm: font size sm (defaultvar(--font-text-xs-size))--badge-font-size-xs: font size xs (defaultvar(--font-text-xs-size))--badge-font-weight-2xs: font weight 2xs (defaultvar(--font-weight-semibold))--badge-font-weight-lg: font weight lg (defaultvar(--font-weight-semibold))--badge-font-weight-md: font weight md (defaultvar(--font-weight-semibold))--badge-font-weight-sm: font weight sm (defaultvar(--font-weight-semibold))--badge-font-weight-xs: font weight xs (defaultvar(--font-weight-semibold))--badge-gutter-2xs: gutter 2xs (default0.1875rem)--badge-gutter-lg: gutter lg (defaultvar(--control-gutter-xs))--badge-gutter-md: gutter md (defaultvar(--control-gutter-2xs))--badge-gutter-sm: gutter sm (defaultcalc(var(--control-gutter-2xs) - 1px))--badge-gutter-xs: gutter xs (default0.25rem)--badge-radius-2xs: radius 2xs (defaultvar(--radius-2xs))--badge-radius-lg: radius lg (defaultvar(--radius-sm))--badge-radius-md: radius md (defaultvar(--radius-xs))--badge-radius-sm: radius sm (defaultvar(--radius-xs))--badge-radius-xs: radius xs (defaultvar(--radius-2xs))--badge-size-2xs: size 2xs (default1rem)--badge-size-lg: size lg (defaultvar(--control-size-2xs))--badge-size-md: size md (defaultvar(--control-size-3xs))--badge-size-sm: size sm (defaultcalc(var(--control-size-3xs) - 2px))--badge-size-xs: size xs (default1.125rem)--badge-tracking-2xs: tracking 2xs (defaultvar(--tracking-wide))--badge-tracking-lg: tracking lg (defaultvar(--tracking-normal))--badge-tracking-md: tracking md (defaultvar(--tracking-normal))--badge-tracking-sm: tracking sm (defaultvar(--tracking-wide))--badge-tracking-xs: tracking xs (defaultvar(--tracking-wide))--button-gap-lg: gap lg (default6px)--button-gap-md: gap md (default4px)--button-gap-sm: gap sm (default3px)--segmented-control-background: background (defaultlight-dark(var(--gray-100), var(--gray-0)))--segmented-control-font-weight: font weight (defaultvar(--font-weight-semibold))--segmented-control-gap: gap (default2px)--segmented-control-gutter: gutter (default2px)--segmented-control-option-highlight-background-color: option highlight background color (defaultlight-dark( var(--gray-200), var(--gray-300) ))--segmented-control-option-highlight-gutter: option highlight gutter (default1px)--segmented-control-thumb-background: thumb background (defaultlight-dark(var(--gray-0), var(--gray-300)))--segmented-control-thumb-shadow: thumb shadow (default0 1px 4px -1px rgb(0 0 0 / 20%))--tabs-underline-border-color: underline border color (defaultvar(--color-border))--tabs-underline-indicator-color: underline indicator color (defaultvar(--color-background-primary-solid))--tabs-underline-indicator-height: underline indicator height (default2px)