Tabs

View switcher with three visual variants (pill, segmented, underline) and three sizes. Optional swipe gesture on mobile and automatic horizontal overflow scroll.

Default

TabsList holds the triggers, each TabsContent renders the panel for its value. Pass default-value to pick the starting tab.

Dark previewReplay previewOpen in new tab

Make changes to your account here. Save when you're done.

Usage

Import the parts you need from the component's folder.

ts
import {
  Tabs,
  TabsList,
  TabsTrigger,
  TabsContent,
  TabsIndicator,
  TabsCarousel,
  TabsCarouselPanel,
  TabsSelectionIndicator,
  TabNav,
} from "@/components/ui/tabs";

Variants

Pill for compact pickers in a toolbar, segmented for equivalent groupings, underline for longer section navigation.

Dark previewReplay previewOpen in new tab
Pill variant.
Segmented variant.
Underline variant.

Underline

variant="underline" gives a transparent list with a sliding bottom border under the active trigger — the line style suited to page-level section navigation.

Dark previewReplay previewOpen in new tab
A high-level summary of the project.

Sizes

Three heights: sm, md (default), and lg. Each follows the same ladder as Button — one step taller on phones, settling to its desktop height at the sm breakpoint.

Dark previewReplay previewOpen in new tab
Size sm (h-7).
Size md (h-8), the default.
Size lg (h-10).

With icons

Drop an Icon inside each trigger alongside the label.

Dark previewReplay previewOpen in new tab
Overview panel.

Disabled trigger

Add disabled to a TabsTrigger to block it.

Dark previewReplay previewOpen in new tab
Account panel.

Overflow scroll

When triggers exceed the width, the list scrolls horizontally instead of wrapping.

Dark previewReplay previewOpen in new tab
January panel. Too many tabs scroll horizontally.

Controlled

Drive the active tab from outside with v-model.

Dark previewReplay previewOpen in new tab
Active: account
Account panel.

Swipe (mobile)

swipe enables left/right gestures to change tabs. Carousels, tables, and nested tablists are excluded automatically.

Dark previewReplay previewOpen in new tab
On mobile, swipe left or right in this area to change tabs.

Swipeable carousel

swipeable turns the panels into a horizontal scroll-snap carousel built with TabsCarousel and TabsCarouselPanel. The active tab follows the scroll position and a scroll-driven TabsSelectionIndicator tracks your finger where supported (Chrome 125+), falling back to the sliding TabsIndicator elsewhere. This is separate from the swipe gesture prop.

Dark previewReplay previewOpen in new tab

home

Swipe or scroll horizontally to move between panels. The indicator follows the scroll position where supported.

files

Swipe or scroll horizontally to move between panels. The indicator follows the scroll position where supported.

settings

Swipe or scroll horizontally to move between panels. The indicator follows the scroll position where supported.

Route tabs (TabNav)

TabNav is a sibling of Tabs for page-level navigation: each tab is a real NuxtLink route, so switching a tab changes the URL. Pass a tabs array of route descriptors. Use TabNav when tabs map to routes; use Tabs when they switch views inside one page without changing the URL.

Dark previewReplay previewOpen in new tab

API Reference

Tabs

PropTypeDefaultDescription
modelValuestring—Active tab value. Supports v-model.
defaultValuestring—Starting active tab when v-model is not used.
variant"pill" | "segmented" | "underline""pill"Visual style of the tab list and triggers.
size"sm" | "md" | "lg""md"Trigger height.
swipebooleanfalseEnable left/right swipe to change tabs on mobile.
swipeablebooleanfalseEnable the scroll-snap carousel mode. Use with TabsCarousel + TabsCarouselPanel and optionally TabsSelectionIndicator. Distinct from swipe.
swipeExcludestring[]["[aria-roledescription=carousel]", ".pswp", ...]CSS selectors excluded from the swipe gesture.
EventDescription
update:modelValueFires when the active tab changes. Enables v-model.

TabsList

PropTypeDefaultDescription
classstring—Row of triggers. Must contain a TabsIndicator for the sliding marker.

TabsTrigger

PropTypeDefaultDescription
valuestring—Identifier matched against the active tab value.
disabledbooleanfalseDisable this trigger.

TabsContent / TabsIndicator

PropTypeDefaultDescription
valuestring—(TabsContent) Panel shown for the matching trigger. TabsIndicator renders the sliding marker.

TabsCarousel

PropTypeDefaultDescription
classstring—Horizontal scroll-snap container. Wraps TabsCarouselPanel children and syncs the active tab with the scroll position. Requires swipeable on Tabs.

TabsCarouselPanel

PropTypeDefaultDescription
valuestring—Carousel panel matched against the active tab value. Always mounted and laid out side by side.

TabsSelectionIndicator

PropTypeDefaultDescription
classstring—Scroll-driven marker that tracks the carousel position. Place inside TabsList; it measures the triggers automatically. Only visible where scroll-driven animations are supported (Chrome 125+).

TabNav

PropTypeDefaultDescription
tabsTab[]—Required. Route-based nav tabs. Each tab: { to: string, label: string, icon?: string, exact?: boolean, activeFor?: string[] }.
classstring—Override the nav layout.

Accessibility

Keyboard shortcuts and ARIA behavior.

Shortcut Description
←Moves to the previous tab (horizontal orientation).
→Moves to the next tab (horizontal orientation).
↑Moves to the previous tab (vertical orientation).
↓Moves to the next tab (vertical orientation).
HomeMoves to the first tab.
EndMoves to the last tab.
EnterActivates the focused tab (manual activation).
SpaceActivates the focused tab (manual activation).
  • Uses a roving tabindex; only the active tab is in the tab sequence.
  • Applies tablist, tab, and tabpanel roles with aria-selected and aria-controls.
  • Tabs activate automatically on focus by default.