---
title: Tabs - Accessible Tab Navigation for Vue 3
meta:
- name: description
  content: Accessible tab navigation with automatic and manual activation modes. WAI-ARIA compliant compound component with roving tabindex and keyboard navigation.
- name: keywords
  content: tabs, tab panel, navigation, Vue 3, headless, accessibility, WAI-ARIA, roving tabindex
features:
  category: Component
  label: 'C: Tabs'
  github: /components/Tabs/
  renderless: false
  level: 2
related:
  - /composables/selection/create-step
  - /components/disclosure/expansion-panel
  - /components/disclosure/dialog
---

# Tabs

A component for creating accessible tabbed interfaces with proper ARIA support and keyboard navigation.

<DocsPageFeatures :frontmatter />

## Usage

Organize content into panels that share the same space, showing one at a time. Bind `v-model` to track the active tab and switch panels declaratively.

::: gn-example
/components/tabs/basic
:::

## Anatomy

```vue Anatomy no-filename
<script setup lang="ts">
  import { Tabs } from '@vuetify/v0'
</script>

<template>
  <Tabs.Root>
    <Tabs.List>
      <Tabs.Item />
    </Tabs.List>

    <Tabs.Panel />
  </Tabs.Root>
</template>
```

## Recipes

### Activation Modes

Control when tabs activate with the `activation` prop:

- **automatic** (default): Arrow keys move focus and activate the tab simultaneously
- **manual**: Arrow keys move focus without activating — the user must press Enter or Space to confirm their selection

```vue
<template>
  <Tabs.Root activation="manual">
    <!-- Tabs only activate on Enter/Space -->
  </Tabs.Root>
</template>
```

### Orientation

Support for both horizontal and vertical tab layouts:

```vue
<template>
  <Tabs.Root orientation="vertical">
    <!-- Arrow Up/Down for navigation instead of Left/Right -->
  </Tabs.Root>
</template>
```

### Circular Navigation

Control whether navigation wraps around at boundaries:

```vue
<template>
  <Tabs.Root :circular="false">
    <!-- Navigation stops at first/last tab -->
  </Tabs.Root>
</template>
```

### Auto-Enrollment

Set `enroll` to auto-select the first registered tab. Useful when tabs are rendered dynamically and the initial selection should track whichever tab mounts first:

```vue
<template>
  <Tabs.Root enroll>
    <!-- First tab to register is automatically selected -->
    <Tabs.Item v-for="tab in dynamicTabs" :key="tab.id" :value="tab.id">
      {{ tab.label }}
    </Tabs.Item>
  </Tabs.Root>
</template>
```

## Accessibility

### Keyboard Navigation

The component implements full WAI-ARIA keyboard support. Keyboard behavior depends on the activation mode:

| Key | Automatic | Manual |
| - | - | - |
| Arrow Left/Right (horizontal) | Moves focus **and** activates tab | Moves focus only |
| Arrow Up/Down (vertical) | Moves focus **and** activates tab | Moves focus only |
| Home | Focuses **and** activates first tab | Focuses first tab only |
| End | Focuses **and** activates last tab | Focuses last tab only |
| Enter/Space | — | Activates the focused tab |

## FAQ

::: faq

??? What's the difference between automatic and manual activation?

With `activation="automatic"` (default), arrow keys move focus and activate the tab in one step. With `activation="manual"`, arrow keys only move focus — the user presses Enter or Space to activate the focused tab.

??? How do I stop keyboard navigation from wrapping at the first and last tab?

Set `:circular="false"` on `Tabs.Root`. Navigation then stops at the first and last tab instead of cycling around.

??? How do I auto-select the first tab when tabs are rendered dynamically?

Add `enroll` to `Tabs.Root`. The first tab to register becomes the active one, which is useful when the tab set is built from data at runtime.

??? How do I lay the tabs out vertically?

Set `orientation="vertical"` on `Tabs.Root`. Keyboard navigation then uses Arrow Up/Down instead of Arrow Left/Right.

??? How do I keep arrow-key focus when a tab is renderless?

Pass `el` on `Tabs.Item` when `as` is `null`, pointing at the real control the slot renders. Arrow, Home, and End then move focus to that node. Without `el`, selection still updates but DOM focus stays put.

:::

<DocsApi />
