Skip to content

Tabs ​

A tab navigation component for switching between content sections. Supports line, card, and pill variants, icons, closable tabs, content panels, and four positions (top, bottom, left, right).

Basic ​

vue
<script setup>
import { ref } from 'vue'
import { VxTabs } from 'veloxui'

const active = ref('home')

const items = [
  { key: 'home', label: 'Home' },
  { key: 'profile', label: 'Profile' },
  { key: 'settings', label: 'Settings' },
]
</script>

<template>
  <VxTabs v-model="active" :items="items" />
</template>

With Icons ​

vue
<VxTabs v-model="active" :items="[
  { key: 'overview', label: 'Overview', icon: 'home' },
  { key: 'analytics', label: 'Analytics', icon: 'chart' },
  { key: 'settings', label: 'Settings', icon: 'settings' },
  { key: 'users', label: 'Users', icon: 'user' },
]" />

Disabled Tab ​

vue
<VxTabs v-model="active" :items="[
  { key: 'general', label: 'General' },
  { key: 'security', label: 'Security' },
  { key: 'billing', label: 'Billing', disabled: true },
  { key: 'notifications', label: 'Notifications' },
]" />

With Badges ^0.1.9 ​

Set badge on a tab item to show a counter. Values greater than 9 display as +9 — hover to see the full number in a tooltip. Use dot: true for a pulse indicator.

vue
<script setup>
import { ref } from 'vue'
import { VxTabs } from 'veloxui'

const active = ref('inbox')

const items = [
  { key: 'inbox', label: 'Inbox', badge: 3 },
  { key: 'drafts', label: 'Drafts', badge: 42 },   // shows "+9", title="42"
  { key: 'spam', label: 'Spam', badge: 128 },      // shows "+9", title="128"
  { key: 'live', label: 'Live', dot: true },
]
</script>

<template>
  <VxTabs v-model="active" :items="items" />
</template>

Full Badge (no truncation) ​

Set fullBadge: true on an item to always show the complete value, even above 9.

vue
<VxTabs v-model="active" :items="[
  { key: 'inbox', label: 'Inbox', badge: 3, fullBadge: true },
  { key: 'drafts', label: 'Drafts', badge: 42, fullBadge: true },
  { key: 'spam', label: 'Spam', badge: 128, fullBadge: true },
]" />

Badges on Segment Variant ​

Badges render the same way inside every variant — here's the segment style.

All issues
132 total issues across open and closed states.
vue
<script setup>
import { ref } from 'vue'
import { VxTabs } from 'veloxui'

const active = ref('all')

const items = [
  { key: 'all', label: 'All', badge: 132 },   // shows "+9", title="132"
  { key: 'open', label: 'Open', badge: 8 },
  { key: 'closed', label: 'Closed', badge: 24 },
]
</script>

<template>
  <VxTabs v-model="active" :items="items" variant="segment">
    <template #panel-all>All issues content…</template>
    <template #panel-open>Open issues content…</template>
    <template #panel-closed>Closed issues content…</template>
  </VxTabs>
</template>

Card Variant ​

vue
<VxTabs v-model="active" :items="items" variant="card" />

Pill Variant ​

vue
<VxTabs v-model="active" :items="items" variant="pill" />

Segment Variant ​

Segmented pill-style tabs with a bordered card body below.

Home
Welcome back! Here is an overview of your recent activity and quick actions.
vue
<script setup>
import { ref } from 'vue'
import { VxTabs, VxInput, VxButton, VxSwitch } from 'veloxui'

const active = ref('home')

const items = [
  { key: 'home', label: 'Home' },
  { key: 'profile', label: 'Profile' },
  { key: 'settings', label: 'Settings' },
]
</script>

<template>
  <VxTabs v-model="active" :items="items" variant="segment">
    <template #panel-home>
      <p>Welcome back! Here is an overview of your activity.</p>
    </template>
    <template #panel-profile>
      <VxInput placeholder="Display name" />
      <VxButton size="sm">Save</VxButton>
    </template>
    <template #panel-settings>
      <div>Dark mode <VxSwitch /></div>
      <div>Notifications <VxSwitch /></div>
    </template>
  </VxTabs>
</template>

Folder Variant ​

Classic folder-tab style — active tab connects seamlessly to the card body below.

Home
Welcome back! Here is an overview of your recent activity and quick actions.
vue
<VxTabs v-model="active" :items="items" variant="folder">
  <template #panel-home>
    <p>Home content here.</p>
  </template>
  <template #panel-profile>
    <p>Profile content here.</p>
  </template>
</VxTabs>

Closable Tabs ​

Set closable: true on tab items. Listen to the close event to remove tabs.

vue
<script setup>
import { ref } from 'vue'
import { VxTabs } from 'veloxui'

const active = ref('tab1')
const items = ref([
  { key: 'tab1', label: 'Welcome', closable: false },
  { key: 'tab2', label: 'Document.vue', closable: true },
  { key: 'tab3', label: 'Settings.ts', closable: true },
])

function closeTab(key) {
  items.value = items.value.filter(t => t.key !== key)
  if (active.value === key) active.value = items.value[0]?.key
}
</script>

<template>
  <VxTabs v-model="active" :items="items" variant="card" @close="closeTab" />
</template>

Sizes ​

Three sizes: sm, md (default), and lg.

vue
<VxTabs :items="items" v-model="active" size="sm" />
<VxTabs :items="items" v-model="active" size="md" />
<VxTabs :items="items" v-model="active" size="lg" />

Block Mode ​

Tabs stretch to fill full width equally.

vue
<VxTabs v-model="active" :items="items" block />

Content Panels ​

Use panel-{key} slots to render content that switches with tabs.

Profile Settings
vue
<VxTabs v-model="active" :items="items">
  <template #panel-profile>
    <VxInput placeholder="Display name" />
    <VxButton size="sm">Save</VxButton>
  </template>
  <template #panel-password>
    <VxInput placeholder="Current password" type="password" />
    <VxInput placeholder="New password" type="password" />
    <VxButton size="sm">Update</VxButton>
  </template>
  <template #panel-team>
    <p>Invite and manage your team members here.</p>
  </template>
</VxTabs>

Vertical (Left / Right) ​

Use position="left" or position="right" for vertical tabs.

General Settings

Manage your general preferences and configuration.

vue
<VxTabs v-model="active" :items="items" position="left">
  <template #panel-settings>
    <p>General settings content...</p>
  </template>
  <template #panel-security>
    <p>Security content...</p>
  </template>
</VxTabs>

Bottom Position ​

Home content with tabs at the bottom.
vue
<VxTabs v-model="active" :items="items" position="bottom">
  <template #panel-home>
    <p>Home content with tabs at the bottom.</p>
  </template>
</VxTabs>

API ​

VxTabs Props ​

PropTypeDefaultDescription
v-modelstring—Active tab key
itemsTabItem[][]Tab items
variant'line' | 'card' | 'pill' | 'segment' | 'folder''line'Visual style
size'sm' | 'md' | 'lg''md'Tab size
position'top' | 'bottom' | 'left' | 'right''top'Tab bar position
blockbooleanfalseStretch tabs to equal width
root-classstring | string[] | object—Class on root

TabItem ​

PropertyTypeRequiredDescription
keystringYesUnique identifier
labelstringYesTab label text
iconstring | ComponentNoTab icon
disabledbooleanNoDisable this tab
closablebooleanNoShow close button
badgestring | numberNoCounter shown next to the label. Numbers greater than 9 collapse to +9; the full value appears in a tooltip on hover
fullBadgebooleanNoAlways show the full badge value without truncation (disables the +9 collapse)
dotbooleanNoShow a small pulse dot instead of a numeric badge

Slots ​

SlotPropsDescription
tab{ item, active }Custom tab button content for all tabs
tab-{key}{ item, active }Custom tab button content for a specific tab
panel{ item, active }Default panel content for all tabs
panel-{key}{ item, active }Panel content for a specific tab
extra—Extra content after tabs in the nav bar

Events ​

EventPayloadDescription
update:modelValue(key: string)Active tab changed
change(key: string)Tab selected
close(key: string)Tab close button clicked