Tabs

Switch between grouped views with segmented or underline tabs, icon-only triggers, and badge counts on each tab.

import { Tabs, TabsTab } from "@plexui/vue/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

width

Tabs shares the unified 9-step size scale with Button, Input, Select, and SelectControl.

Migration from SegmentedControl

Tabs replaces and extends SegmentedControl. As in the React package, the old import still works as an alias:

<script setup lang="ts">
import { ref } from "vue"
// Old (still works)
import { SegmentedControl, SegmentedControlOption } from "@plexui/vue/components/SegmentedControl"
// New (recommended)
import { Tabs, TabsTab } from "@plexui/vue/components/Tabs"

const mode = ref("a")
</script>

<template>
  <SegmentedControl v-model:value="mode" aria-label="Mode">
    <SegmentedControlOption value="a">A</SegmentedControlOption>
  </SegmentedControl>

  <Tabs v-model:value="mode" aria-label="Mode">
    <TabsTab value="a">A</TabsTab>
  </Tabs>
</template>

TabsTab and TabsOption are the same component, and so are SegmentedControlOption and SegmentedControlTab. The SegmentedControl alias defaults to variant="segmented".

API

Tabs (root)

PropTypeDefaultDescription
valuestring—Selected tab value. Bind with v-model:value; leave unset for an uncontrolled group
variant"segmented" | "underline""segmented"Visual style: segmented (background highlight) or underline (line indicator)
orientation"horizontal" | "vertical""horizontal"Layout direction of the tab group
size"3xs" | "2xs" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl" | "3xl""md"Control height (3xs through 3xl)
gutter-size"2xs" | "xs" | "sm" | "md" | "lg" | "xl"—Horizontal padding of tabs
pillbooleantrueFully rounded control (segmented variant only)
flushbooleanfalseText-width indicator, no border, gap spacing (underline variant only)
blockbooleanfalseFull-width control with equal-width tabs
disabledbooleanfalseDisable all tabs
aria-labelstring—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)
overflow-labelstring"More"Text of the menu button with overflow="menu"
classstring—Extra classes on the group element
default slotVNode[]—TabsTab children
@update:value(value: string) => void—Emitted when a tab is selected; powers v-model:value
@change(value: string) => void—Emitted with update:value, named after the React onChange prop
@click(event: MouseEvent) => void—Emitted on any click in the group, even when the selection does not change

TabsTab

PropTypeDefaultDescription
valuestring—Tab value (required)
disabledboolean—Disable this tab
iconComponent | VNode | string—Icon before the label (sized automatically); the icon slot takes precedence
badgenumber | string | VNode | { content; color?; variant?; pill?; loading? }—Badge/count or custom badge config
aria-labelstring—Accessible name (required for icon-only tabs)
default slotVNode[]—Tab label
icon slotVNode[]—Icon before the label
badge slotVNode[]—Badge content; styling still comes from the badge object

Styling

Tabs reads these component tokens. Override them at any scope to restyle it:

  • --badge-font-size-2xs: font size 2xs (default var(--font-text-xs-size))
  • --badge-font-size-lg: font size lg (default var(--font-text-sm-size))
  • --badge-font-size-md: font size md (default var(--font-text-sm-size))
  • --badge-font-size-sm: font size sm (default var(--font-text-xs-size))
  • --badge-font-size-xs: font size xs (default var(--font-text-xs-size))
  • --badge-font-weight-2xs: font weight 2xs (default var(--font-weight-semibold))
  • --badge-font-weight-lg: font weight lg (default var(--font-weight-semibold))
  • --badge-font-weight-md: font weight md (default var(--font-weight-semibold))
  • --badge-font-weight-sm: font weight sm (default var(--font-weight-semibold))
  • --badge-font-weight-xs: font weight xs (default var(--font-weight-semibold))
  • --badge-gutter-2xs: gutter 2xs (default 0.1875rem)
  • --badge-gutter-lg: gutter lg (default var(--control-gutter-xs))
  • --badge-gutter-md: gutter md (default var(--control-gutter-2xs))
  • --badge-gutter-sm: gutter sm (default calc(var(--control-gutter-2xs) - 1px))
  • --badge-gutter-xs: gutter xs (default 0.25rem)
  • --badge-radius-2xs: radius 2xs (default var(--radius-2xs))
  • --badge-radius-lg: radius lg (default var(--radius-sm))
  • --badge-radius-md: radius md (default var(--radius-xs))
  • --badge-radius-sm: radius sm (default var(--radius-xs))
  • --badge-radius-xs: radius xs (default var(--radius-2xs))
  • --badge-size-2xs: size 2xs (default 1rem)
  • --badge-size-lg: size lg (default var(--control-size-2xs))
  • --badge-size-md: size md (default var(--control-size-3xs))
  • --badge-size-sm: size sm (default calc(var(--control-size-3xs) - 2px))
  • --badge-size-xs: size xs (default 1.125rem)
  • --badge-tracking-2xs: tracking 2xs (default var(--tracking-wide))
  • --badge-tracking-lg: tracking lg (default var(--tracking-normal))
  • --badge-tracking-md: tracking md (default var(--tracking-normal))
  • --badge-tracking-sm: tracking sm (default var(--tracking-wide))
  • --badge-tracking-xs: tracking xs (default var(--tracking-wide))
  • --button-gap-lg: gap lg (default 6px)
  • --button-gap-md: gap md (default 4px)
  • --button-gap-sm: gap sm (default 3px)
  • --segmented-control-background: background (default light-dark(var(--gray-100), var(--gray-0)))
  • --segmented-control-font-weight: font weight (default var(--font-weight-semibold))
  • --segmented-control-gap: gap (default 2px)
  • --segmented-control-gutter: gutter (default 2px)
  • --segmented-control-option-highlight-background-color: option highlight background color (default light-dark( var(--gray-200), var(--gray-300) ))
  • --segmented-control-option-highlight-gutter: option highlight gutter (default 1px)
  • --segmented-control-thumb-background: thumb background (default light-dark(var(--gray-0), var(--gray-300)))
  • --segmented-control-thumb-shadow: thumb shadow (default 0 1px 4px -1px rgb(0 0 0 / 20%))
  • --tabs-underline-border-color: underline border color (default var(--color-border))
  • --tabs-underline-indicator-color: underline indicator color (default var(--color-background-primary-solid))
  • --tabs-underline-indicator-height: underline indicator height (default 2px)