Skip to main content

Usage

The Tabs component allows users to switch between different views or sections of content. It supports icons, avatars, badges, and various orientations.

Basic Example

<template>
  <UTabs :items="items" />
</template>

<script setup>
const items = [
  { label: 'Account', content: 'Make changes to your account here.' },
  { label: 'Password', content: 'Change your password here.' },
  { label: 'Settings', content: 'Manage your settings here.' }
]
</script>

With Icons

<template>
  <UTabs :items="items" />
</template>

<script setup>
const items = [
  { label: 'Home', icon: 'i-lucide-home', content: 'Welcome home!' },
  { label: 'Settings', icon: 'i-lucide-settings', content: 'Adjust your settings.' },
  { label: 'Profile', icon: 'i-lucide-user', content: 'View your profile.' }
]
</script>

With Badges

<template>
  <UTabs :items="items" />
</template>

<script setup>
const items = [
  { label: 'Inbox', badge: 5, content: 'You have 5 new messages.' },
  { label: 'Sent', badge: 0, content: 'No sent messages.' },
  { label: 'Drafts', badge: { label: '3', color: 'primary' }, content: '3 drafts saved.' }
]
</script>

Vertical Orientation

<template>
  <UTabs :items="items" orientation="vertical" />
</template>

<script setup>
const items = [
  { label: 'Account', content: 'Make changes to your account here.' },
  { label: 'Password', content: 'Change your password here.' },
  { label: 'Settings', content: 'Manage your settings here.' }
]
</script>

Different Variants

<template>
  <div class="space-y-4">
    <UTabs :items="items" variant="pill" />
    <UTabs :items="items" variant="link" />
  </div>
</template>

<script setup>
const items = [
  { label: 'Tab 1', content: 'Content 1' },
  { label: 'Tab 2', content: 'Content 2' },
  { label: 'Tab 3', content: 'Content 3' }
]
</script>

Controlled State

<template>
  <div>
    <UTabs v-model="selectedTab" :items="items" />
    <p class="mt-4">Current tab: {{ selectedTab }}</p>
  </div>
</template>

<script setup>
const selectedTab = ref('1')

const items = [
  { label: 'First', value: '1', content: 'First tab content' },
  { label: 'Second', value: '2', content: 'Second tab content' },
  { label: 'Third', value: '3', content: 'Third tab content' }
]
</script>

Disabled Tabs

<template>
  <UTabs :items="items" />
</template>

<script setup>
const items = [
  { label: 'Available', content: 'This tab is available.' },
  { label: 'Disabled', content: 'This content cannot be accessed.', disabled: true },
  { label: 'Also Available', content: 'This tab is also available.' }
]
</script>

Without Content

<template>
  <UTabs v-model="selectedTab" :items="items" :content="false" />
  
  <!-- Custom content outside tabs -->
  <div class="mt-4">
    <div v-if="selectedTab === '0'">Custom content for tab 1</div>
    <div v-else-if="selectedTab === '1'">Custom content for tab 2</div>
    <div v-else>Custom content for tab 3</div>
  </div>
</template>

<script setup>
const selectedTab = ref('0')

const items = [
  { label: 'Tab 1' },
  { label: 'Tab 2' },
  { label: 'Tab 3' }
]
</script>

API

Props

items
TabsItem[]
Array of tab items to display.
modelValue
string | number
The controlled value of the active tab (v-model).
defaultValue
string | number
default:"'0'"
The default active tab value when uncontrolled.
as
any
default:"'div'"
The element or component this component should render as.
color
string
default:"'primary'"
The color theme of the tabs.
variant
string
default:"'pill'"
The visual variant of the tabs. Options: pill, link.
size
string
default:"'md'"
The size of the tabs. Options: xs, sm, md, lg, xl.
orientation
string
default:"'horizontal'"
The orientation of the tabs. Options: horizontal, vertical.
content
boolean
default:"true"
Whether to render the content panels. Set to false to manage content externally.
activationMode
string
How tabs are activated. Options: automatic, manual.
unmountOnHide
boolean
default:"true"
Whether to unmount inactive tab content from the DOM.
valueKey
string
default:"'value'"
The key used to get the value from the item.
labelKey
string
default:"'label'"
The key used to get the label from the item.
class
any
Additional CSS classes to apply to the root element.
ui
object
Custom UI configuration for slots.

TabsItem

label
string
The text label for the tab.
value
string | number
A unique value for the tab item. Defaults to the index.
icon
string
An Iconify icon name to display before the label.
avatar
AvatarProps
Avatar configuration to display before the label.
badge
string | number | BadgeProps
Display a badge on the tab. Can be a simple value or full badge configuration.
content
string
The content to display in the tab panel.
slot
string
Custom slot name for this tab’s content.
disabled
boolean
Whether the tab is disabled.
class
any
Additional CSS classes for the tab.
ui
object
Custom UI configuration for this tab’s slots.

Emits

update:modelValue
(value: string | number) => void
Emitted when the active tab changes.

Slots

default

Customize the tab label.
<template>
  <UTabs :items="items">
    <template #default="{ item, index }">
      <span class="uppercase">{{ item.label }}</span>
    </template>
  </UTabs>
</template>

leading

Customize the leading icon or avatar for all tabs.
<template>
  <UTabs :items="items">
    <template #leading="{ item, index, ui }">
      <UIcon :name="item.icon" class="text-primary" />
    </template>
  </UTabs>
</template>

trailing

Customize the trailing badge or add custom trailing content.
<template>
  <UTabs :items="items">
    <template #trailing="{ item, index, ui }">
      <UBadge v-if="item.count" :label="item.count" />
    </template>
  </UTabs>
</template>

content

Customize the content panel for all tabs.
<template>
  <UTabs :items="items">
    <template #content="{ item, index, ui }">
      <div class="p-4">
        <h3>{{ item.label }}</h3>
        <p>{{ item.content }}</p>
      </div>
    </template>
  </UTabs>
</template>

list-leading

Add content before the tab list.
<template>
  <UTabs :items="items">
    <template #list-leading>
      <UButton icon="i-lucide-plus" size="xs" />
    </template>
  </UTabs>
</template>

list-trailing

Add content after the tab list.
<template>
  <UTabs :items="items">
    <template #list-trailing>
      <UButton icon="i-lucide-settings" size="xs" />
    </template>
  </UTabs>
</template>

Dynamic Slots

You can use dynamic slots based on the slot property of items:
<template>
  <UTabs :items="items">
    <template #special-content="{ item, index, ui }">
      <div class="special-content">
        This is special content!
      </div>
    </template>
  </UTabs>
</template>

<script setup>
const items = [
  { label: 'Normal', content: 'Normal content' },
  { label: 'Special', slot: 'special' }
]
</script>

Build docs developers (and LLMs) love