Skip to main content

Overview

Tabs provides an accessible tab interface with full keyboard navigation support, roving tabindex, and both automatic and manual activation modes. It supports horizontal and vertical orientations.

Sub-Components

  • Tabs.Root: Renderless container that manages tab state
  • Tabs.List: Container for tab triggers with tablist role
  • Tabs.Item: Individual tab trigger with keyboard navigation
  • Tabs.Panel: Content panel associated with a tab

Usage

<script lang="ts" setup>
import { ref } from 'vue'
import { Tabs } from '@vuetify/v0'

const selected = ref('profile')
</script>

<template>
  <Tabs.Root v-model="selected">
    <Tabs.List label="Account settings">
      <Tabs.Item value="profile">Profile</Tabs.Item>
      <Tabs.Item value="password">Password</Tabs.Item>
      <Tabs.Item value="billing" disabled>Billing</Tabs.Item>
    </Tabs.List>

    <Tabs.Panel value="profile">Profile content</Tabs.Panel>
    <Tabs.Panel value="password">Password content</Tabs.Panel>
    <Tabs.Panel value="billing">Billing content</Tabs.Panel>
  </Tabs.Root>
</template>

Tabs.Root

Props

namespace
string
default:"'v0:tabs'"
Namespace for dependency injection (must match child namespace)
disabled
boolean
default:"false"
Disables the entire tabs instance
enroll
boolean
default:"false"
Auto-select non-disabled items on registration
mandatory
boolean | 'force'
default:"'force'"
Controls mandatory tab behavior:
  • false: No mandatory tab enforcement
  • true: Prevents deselecting the last selected item
  • 'force' (default): Automatically selects the first non-disabled tab
circular
boolean
default:"true"
Whether arrow key navigation wraps around
orientation
'horizontal' | 'vertical'
default:"'horizontal'"
Tab orientation for keyboard navigation
activation
'automatic' | 'manual'
default:"'automatic'"
Activation mode:
  • automatic: Tab activates on focus (arrow keys)
  • manual: Tab activates on Enter/Space only

Model

v-model
T | T[]
Current tab value(s)

Slot Props

isDisabled
boolean
Whether the tabs instance is disabled
orientation
'horizontal' | 'vertical'
Current orientation
activation
'automatic' | 'manual'
Current activation mode
first
() => void
Select the first tab
last
() => void
Select the last tab
next
() => void
Select the next tab
prev
() => void
Select the previous tab
step
(count: number) => void
Step forward or backward by a specific count
select
(id: ID) => void
Select a tab by ID
unselect
(id: ID) => void
Unselect a tab by ID
toggle
(id: ID) => void
Toggle a tab’s selection state by ID
attrs
object
Attributes including aria-multiselectable: false

Tabs.List

Props

as
DOMElement | null
default:"'div'"
The HTML element to render as
label
string
Accessible label for the tab list

Slot Props

orientation
'horizontal' | 'vertical'
Current orientation
attrs
object
Attributes including role=“tablist” and aria-orientation

Tabs.Item

Props

as
DOMElement | null
default:"'button'"
The HTML element to render as
id
ID
Unique identifier (auto-generated if not provided)
value
V
Value associated with this tab (used to match with TabsPanel)
disabled
MaybeRef<boolean>
Disables this specific tab
namespace
string
default:"'v0:tabs'"
Namespace for dependency injection
ariaLabel
string
Accessible label for this tab
ariaLabelledby
string
ID of element that labels this tab
ariaDescribedby
string
ID of element that describes this tab

Slot Props

id
string
Unique identifier
isSelected
boolean
Whether this tab is currently selected
isDisabled
boolean
Whether this tab is disabled
select
() => void
Select this tab
attrs
object
Attributes including role, tabindex, aria-selected, aria-controls, event handlers, etc.

Tabs.Panel

Props

as
DOMElement | null
default:"'div'"
The HTML element to render as
value
V
Value that matches this panel with a Tabs.Item
namespace
string
default:"'v0:tabs'"
Namespace for dependency injection

Slot Props

isSelected
boolean
Whether this panel is currently visible
attrs
object
Attributes including role=“tabpanel”, aria-labelledby, and tabindex

Examples

<script setup>
import { ref } from 'vue'
import { Tabs } from '@vuetify/v0'

const selected = ref('profile')
</script>

<template>
  <Tabs.Root v-model="selected">
    <Tabs.List label="Account settings">
      <Tabs.Item value="profile">Profile</Tabs.Item>
      <Tabs.Item value="password">Password</Tabs.Item>
    </Tabs.List>

    <Tabs.Panel value="profile">
      Profile content
    </Tabs.Panel>

    <Tabs.Panel value="password">
      Password content
    </Tabs.Panel>
  </Tabs.Root>
</template>

Keyboard Navigation

Horizontal (default)

  • ArrowRight: Move to next tab
  • ArrowLeft: Move to previous tab
  • Home: Move to first tab
  • End: Move to last tab
  • Enter/Space: Activate tab (manual mode only)

Vertical

  • ArrowDown: Move to next tab
  • ArrowUp: Move to previous tab
  • Home: Move to first tab
  • End: Move to last tab
  • Enter/Space: Activate tab (manual mode only)

Accessibility

  • Tabs.List has role="tablist" and aria-orientation
  • Tabs.Item has role="tab", roving tabindex, and aria-selected
  • Tabs.Panel has role="tabpanel" and aria-labelledby pointing to its tab
  • Focus management with keyboard navigation
  • Disabled tabs are skipped in navigation
<template>
  <Tabs.Root v-model="selected">
    <Tabs.List label="Settings">
      <Tabs.Item value="profile" aria-label="Profile settings">
        Profile
      </Tabs.Item>
    </Tabs.List>

    <Tabs.Panel value="profile">
      Profile content
    </Tabs.Panel>
  </Tabs.Root>
</template>

SSR

Tabs is fully compatible with SSR. The Root component is renderless by default:
<template>
  <Tabs.Root v-model="selected">
    <Tabs.List label="Account settings">
      <Tabs.Item value="profile">Profile</Tabs.Item>
      <Tabs.Item value="password">Password</Tabs.Item>
    </Tabs.List>

    <Tabs.Panel value="profile">Profile content</Tabs.Panel>
    <Tabs.Panel value="password">Password content</Tabs.Panel>
  </Tabs.Root>
</template>

Build docs developers (and LLMs) love