Tabs

A set of layered sections of content—known as tab panels—that are displayed one at a time.

Component Features

  • 🎨 3 Visual Variants: Supports line, segment, pill visual variants.
  • 📐 4 Positions: Supports top, bottom, left, right tab positions.
  • 📱 Scrollable: Supports horizontal scroll when tabs overflow.
  • ✖️ Closable: Supports closable tab panels.
  • Draggable: Supports drag-to-reorder tabs.
  • Lazy Load: Supports lazy rendering of tab panel content.
  • 📱 Responsive Folding: Supports responsive folding of tab overflow.
  • 🎨 Theme Customization: Based on BrConfigProvider for global theming and TailwindCSS local overrides.

Basic Usage

<script setup lang="ts">
import { BrTabs, BrTabsList, BrTabsTrigger, BrTabsContent } from '@breezeui/vue'
</script>

<template>
  <BrTabs default-value="account" class="w-full">
    <BrTabsList>
      <BrTabsTrigger value="account">Account</BrTabsTrigger>
      <BrTabsTrigger value="password">Password</BrTabsTrigger>
    </BrTabsList>
    <BrTabsContent value="account">Make changes to your account here.</BrTabsContent>
    <BrTabsContent value="password">Change your password here.</BrTabsContent>
  </BrTabs>
</template>

Variants

Use the variant prop to control the visual style of the tabs.

  • Line: Default style with a bottom border and an active indicator.
  • Card: Card style with borders.
  • Underline: Simple underline style.
<script setup lang="ts">
import { BrTabs, BrTabsList, BrTabsTrigger, BrTabsContent } from '@breezeui/vue'
</script>

<template>
  <div class="space-y-4 w-full">
    <div class="space-y-2">
      <h3 class="text-sm font-medium">Line Variant</h3>
      <BrTabs default-value="tab1" variant="line" class="w-full">
        <BrTabsList>
          <BrTabsTrigger value="tab1">Tab 1</BrTabsTrigger>
          <BrTabsTrigger value="tab2">Tab 2</BrTabsTrigger>
        </BrTabsList>
        <BrTabsContent value="tab1" class="p-4 border rounded-md">Content 1</BrTabsContent>
        <BrTabsContent value="tab2" class="p-4 border rounded-md">Content 2</BrTabsContent>
      </BrTabs>
    </div>

    <div class="space-y-2">
      <h3 class="text-sm font-medium">Card Variant</h3>
      <BrTabs default-value="tab1" variant="card" class="w-full">
        <BrTabsList>
          <BrTabsTrigger value="tab1">Tab 1</BrTabsTrigger>
          <BrTabsTrigger value="tab2">Tab 2</BrTabsTrigger>
        </BrTabsList>
        <BrTabsContent value="tab1" class="p-4 border rounded-md mt-2">Content 1</BrTabsContent>
        <BrTabsContent value="tab2" class="p-4 border rounded-md mt-2">Content 2</BrTabsContent>
      </BrTabs>
    </div>

    <div class="space-y-2">
      <h3 class="text-sm font-medium">Underline Variant</h3>
      <BrTabs default-value="tab1" variant="underline" class="w-full">
        <BrTabsList>
          <BrTabsTrigger value="tab1">Tab 1</BrTabsTrigger>
          <BrTabsTrigger value="tab2">Tab 2</BrTabsTrigger>
        </BrTabsList>
        <BrTabsContent value="tab1" class="p-4 border rounded-md">Content 1</BrTabsContent>
        <BrTabsContent value="tab2" class="p-4 border rounded-md">Content 2</BrTabsContent>
      </BrTabs>
    </div>
  </div>
</template>

Vertical Tabs

Use the position prop to control the position of the tabs list.

<script setup lang="ts">
import { BrTabs, BrTabsList, BrTabsTrigger, BrTabsContent } from '@breezeui/vue'
</script>

<template>
  <BrTabs default-value="account" position="left" class="w-full h-[300px]">
    <BrTabsList class="w-32">
      <BrTabsTrigger value="account">Account</BrTabsTrigger>
      <BrTabsTrigger value="password">Password</BrTabsTrigger>
      <BrTabsTrigger value="notifications">Notifications</BrTabsTrigger>
      <BrTabsTrigger value="display">Display</BrTabsTrigger>
    </BrTabsList>
    <BrTabsContent value="account" class="p-6">Account settings here.</BrTabsContent>
    <BrTabsContent value="password" class="p-6">Password settings here.</BrTabsContent>
    <BrTabsContent value="notifications" class="p-6">Notification settings here.</BrTabsContent>
    <BrTabsContent value="display" class="p-6">Display settings here.</BrTabsContent>
  </BrTabs>
</template>

Scrollable Tabs

Set the scrollable prop on BrTabsList to enable scrolling when tabs exceed the container width.

<script setup lang="ts">
import { BrTabs, BrTabsList, BrTabsTrigger, BrTabsContent } from '@breezeui/vue'
</script>

<template>
  <BrTabs default-value="tab1" class="w-full">
    <BrTabsList scrollable>
      <BrTabsTrigger v-for="i in 15" :key="i" :value="`tab${i}`">
        Tab {{ i }}
      </BrTabsTrigger>
    </BrTabsList>
    <BrTabsContent v-for="i in 15" :key="i" :value="`tab${i}`" class="p-4 border rounded-md mt-2">
      Content {{ i }}
    </BrTabsContent>
  </BrTabs>
</template>

Closable Tabs

Set the closable prop on BrTabs or BrTabsTrigger to make tabs closable.

<script setup lang="ts">
import { ref } from 'vue'
import { BrTabs, BrTabsList, BrTabsTrigger, BrTabsContent } from '@breezeui/vue'

const activeTab = ref('tab1')

const tabs = ref([
  { value: 'tab1', title: 'Tab 1', content: 'Content 1' },
  { value: 'tab2', title: 'Tab 2', content: 'Content 2' },
  { value: 'tab3', title: 'Tab 3', content: 'Content 3' },
])

const handleClose = (value: string | number) => {
  const index = tabs.value.findIndex(tab => tab.value === value)
  if (index === -1) return

  tabs.value.splice(index, 1)

  // If the active one is closed tab,automatically activate the previous or next one
  if (activeTab.value === value) {
    if (tabs.value.length > 0) {
      const nextIndex = index >= tabs.value.length ? index - 1 : index
      activeTab.value = tabs.value[nextIndex].value
    } else {
      activeTab.value = ''
    }
  }
}
</script>

<template>
  <BrTabs v-model="activeTab" class="w-full" closable>
    <BrTabsList>
      <BrTabsTrigger 
        v-for="tab in tabs" 
        :key="tab.value" 
        :value="tab.value"
        @close="handleClose"
      >
        {{ tab.title }}
      </BrTabsTrigger>
    </BrTabsList>
    <BrTabsContent 
      v-for="tab in tabs" 
      :key="tab.value" 
      :value="tab.value"
      class="p-4 border rounded-md mt-2"
    >
      {{ tab.content }}
    </BrTabsContent>
  </BrTabs>
</template>

Theming

Global Customization (BrConfigProvider)

You can override default CSS variables via the theme prop of BrConfigProvider.

<script setup lang="ts">
import { BrTabs, BrTabsList, BrTabsTrigger, BrTabsContent, BrConfigProvider } from '@breezeui/vue'

const theme = {
  primary: '#10b981', // emerald-500
  radius: 0.5,
}
</script>

<template>
  <BrConfigProvider :theme="theme">
    <div class="space-y-4 w-full">
      <h3 class="font-medium">Emerald Theme with ConfigProvider</h3>
      <BrTabs default-value="account" variant="line" class="w-full">
        <BrTabsList>
          <BrTabsTrigger value="account">Account</BrTabsTrigger>
          <BrTabsTrigger value="password">Password</BrTabsTrigger>
        </BrTabsList>
        <BrTabsContent value="account" class="p-4 border mt-2">Account (Emerald Theme)</BrTabsContent>
        <BrTabsContent value="password" class="p-4 border mt-2">Password (Emerald Theme)</BrTabsContent>
      </BrTabs>
    </div>
  </BrConfigProvider>
</template>

API

BrTabs Props

NameTypeDefaultDescription
variantstring'line'Visual style variants: line, card, underline
positionstring'top'Position of the tabs list: top, right, bottom, left
responsivebooleanfalseWhether the tabs are responsive
closablebooleanfalseWhether the tabs are closable
draggablebooleanfalseWhether the tabs are draggable
lazyLoadbooleantrueWhether the tabs content should be lazy loaded
limitnumber0The maximum number of visible tabs before collapsing

Plus all props from Radix Vue TabsRoot.

BrTabsList Props

NameTypeDefaultDescription
scrollablebooleanfalseWhether the tabs list should be scrollable

Plus all props from Radix Vue TabsList.

BrTabsTrigger Props

NameTypeDefaultDescription
closablebooleanundefinedWhether the tab is closable. Overrides parent closable
draggablebooleanundefinedWhether the tab is draggable. Overrides parent draggable

Plus all props from Radix Vue TabsTrigger.

BrTabsContent Props

All props from Radix Vue TabsContent.

Emits

NameDescriptionParameters
update:modelValueEmitted when the selected tab changes`(value: string
closeEmitted when a tab close button is clicked`(value: string
drag-endEmitted when drag ends`(newOrder: (string