Skip to content

Tabs ​

A neo-brutalist style tab navigation component built on top of reka-ui's Tabs primitive. Supports horizontal/vertical layouts, controlled mode, and multiple active state color variants.

Demo ​

Preview

水平布局(默认)

在此修改您的账户信息。完成后请点击保存。

垂直布局

通用设置选项,包括语言、主题等基础配置。

数据驱动模式(tabs prop)

概览

Installation ​

pnpm dlx brutx-vue@latest add tabs

Usage ​

vue
<script setup>
import { Tabs, TabsList, TabsTrigger, TabsContent } from 'brutx-ui-vue/tabs'
</script>

<template>
    <Tabs default-value="account">
        <TabsList>
            <TabsTrigger value="account">Account</TabsTrigger>
            <TabsTrigger value="password">Password</TabsTrigger>
        </TabsList>
        <TabsContent value="account">
            <p class="text-sm">Manage your account settings.</p>
        </TabsContent>
        <TabsContent value="password">
            <p class="text-sm">Change your password here.</p>
        </TabsContent>
    </Tabs>
</template>

Vertical Layout ​

Set the orientation prop on Tabs to vertical for a vertical layout. In vertical mode, TabsList automatically switches to a vertical arrangement (flex-col), making it suitable for sidebar navigation and similar scenarios.

The orientation prop is passed to child components via dependency injection, so TabsList automatically adapts to the direction without needing to be set individually. If you need to override the direction on a single TabsList, you can set its orientation prop directly.

vue
<script setup>
import { Tabs, TabsList, TabsTrigger, TabsContent } from 'brutx-ui-vue/tabs'
</script>

<template>
    <Tabs default-value="general" orientation="vertical" class="flex gap-4">
        <TabsList>
            <TabsTrigger value="general">General</TabsTrigger>
            <TabsTrigger value="security">Security</TabsTrigger>
            <TabsTrigger value="notifications">Notifications</TabsTrigger>
        </TabsList>
        <TabsContent value="general">
            <p class="text-sm">General settings options.</p>
        </TabsContent>
        <TabsContent value="security">
            <p class="text-sm">Security settings options.</p>
        </TabsContent>
        <TabsContent value="notifications">
            <p class="text-sm">Notification settings options.</p>
        </TabsContent>
    </Tabs>
</template>

Controlled Mode ​

Use v-model for controlled tab switching:

vue
<script setup>
import { ref } from 'vue'
import { Tabs, TabsList, TabsTrigger, TabsContent } from 'brutx-ui-vue/tabs'

const currentTab = ref('account')
</script>

<template>
    <Tabs v-model="currentTab">
        <TabsList>
            <TabsTrigger value="account">Account</TabsTrigger>
            <TabsTrigger value="password">Password</TabsTrigger>
        </TabsList>
        <TabsContent value="account">
            <p class="text-sm">Manage your account settings.</p>
        </TabsContent>
        <TabsContent value="password">
            <p class="text-sm">Change your password here.</p>
        </TabsContent>
    </Tabs>
</template>

Data-driven Mode (tabs Prop) ​

Pass a tabs array to render TabsList, TabsTrigger, and default TabsContent panels automatically. Omit tabs to compose the complete structure through the default slot.

vue
<script setup lang="ts">
import { Tabs } from 'brutx-ui-vue/tabs'
import type { TabItem } from 'brutx-ui-vue/tabs'

const tabs: TabItem[] = [
    { label: 'Overview', value: 'overview' },
    { label: 'Analytics', value: 'analytics' },
    { label: 'Settings', value: 'settings' },
]
</script>

<template>
    <Tabs :tabs="tabs" default-value="overview" />
</template>

Custom Content Panels ​

The default slot replaces the generated Card panels while TabsList continues to be generated from tabs:

vue
<script setup lang="ts">
import { Tabs, TabsContent } from 'brutx-ui-vue/tabs'
import type { TabItem } from 'brutx-ui-vue/tabs'

const tabs: TabItem[] = [
    { label: 'Tab A', value: 'a' },
    { label: 'Tab B', value: 'b' },
]
</script>

<template>
    <Tabs :tabs="tabs">
        <template #default>
            <TabsContent value="a">
                <p class="text-sm">Custom content for A</p>
            </TabsContent>
            <TabsContent value="b">
                <p class="text-sm">Custom content for B</p>
            </TabsContent>
        </template>
    </Tabs>
</template>

In data-driven mode, the header and footer slots add content above and below the tab region. An empty tabs array displays a localized Result empty state while retaining these slots.

Controlled and Uncontrolled State ​

  • Providing modelValue or using v-model makes the parent control the active value.
  • Omitting modelValue lets the component maintain its active value internally.
  • The initial selection uses defaultValue, then the first item value. If the selected item is removed, the same fallback order applies.

Variants ​

TabsTrigger supports the following active state color variants:

VariantDescription
defaultDefault active state style
primaryPrimary (coral) background
secondarySecondary background
successSuccess (green) background
vue
<template>
    <TabsTrigger value="tab" variant="primary">Primary variant</TabsTrigger>
</template>

Sizes ​

TabsList supports the following container sizes:

SizeDescription
smSmall
defaultDefault
lgLarge

Sub-components ​

ComponentDescription
TabsRoot component (wraps reka-ui's TabsRoot)
TabsListTab trigger container
TabsTriggerClickable tab button
TabsContentContent panel for each tab

Exported Types ​

Import from the brutx-ui-vue/tabs sub-path:

ts
import {
    Tabs,
    TabsList,
    TabsTrigger,
    TabsContent,
    tabsListVariants,
    tabsTriggerVariants,
    tabsContentVariants,
} from 'brutx-ui-vue/tabs'
import type { TabItem } from 'brutx-ui-vue/tabs'
import { TabsRoot } from 'reka-ui'

TabItem ​

The data item accepted by the tabs prop:

ts
interface TabItem {
    label: string
    value: string
    disabled?: boolean
}
FieldTypeDescription
labelstringVisible tab label
valuestringUnique tab identifier
disabledbooleanWhether this tab is disabled (optional)

Composables ​

The component exports the following variant utility functions for custom style extensions:

ts
import {
    tabsListVariants,
    tabsTriggerVariants,
    tabsContentVariants,
} from 'brutx-ui-vue/tabs'
FunctionVariant ParametersDescription
tabsListVariantssize: 'sm' | 'default' | 'lg', orientation: 'horizontal' | 'vertical'Container style variants
tabsTriggerVariantsvariant: 'default' | 'primary' | 'secondary' | 'success'Trigger style variants
tabsContentVariants—Content panel base style

API Reference ​

Tabs

Tabs — Props
NameTypeDefaultDescription
modelValue
string | undefined
undefined
The active tab value in controlled mode, supporting v-model. When undefined, the component maintains selection internally.
Details

Declared type

string | undefined

Default value details

Declaration
undefined

Source: packages/ui/src/components/tabs/Tabs.vue

Resolved value
undefined

Source

Tabs.vue:16

packages/ui/src/components/tabs/Tabs.vue

defaultValue
string | undefined
undefined

Runtime fallback:When omitted, data-driven mode uses the first tabs item value; composition mode leaves initial state handling to TabsRoot.

The initial uncontrolled tab value, also used as a fallback when the current selection disappears from the data list.
Details

Declared type

string | undefined

Default value details

Declaration
undefined

Source: packages/ui/src/components/tabs/Tabs.vue

Resolved value
undefined
Runtime fallback
When omitted, data-driven mode uses the first tabs item value; composition mode leaves initial state handling to TabsRoot.

Applied by the component under the documented runtime conditions.

Source

Tabs.vue:17

packages/ui/src/components/tabs/Tabs.vue

tabs
TabItem[] | undefined
undefined
The tab data list. A non-empty list renders triggers and default panels, an empty list shows a localized empty state, and omission enables composition through the default slot.
Details

Declared type

TabItem[] | undefined

Referenced types

TabItem
Type definition — TabItem
export interface TabItem {
    label: string
    value: string
    disabled?: boolean
}

Default value details

Declaration
undefined

Source: packages/ui/src/components/tabs/Tabs.vue

Resolved value
undefined

Source

Tabs.vue:18

packages/ui/src/components/tabs/Tabs.vue

orientation
"vertical" | "horizontal" | undefined
"horizontal"
The root tab orientation for layout state and keyboard navigation, also providing the default orientation for TabsList.
Details

Declared type

"vertical" | "horizontal" | undefined

Literal values

  • "horizontal"
  • "vertical"

Default value details

Declaration
'horizontal'

Source: packages/ui/src/components/tabs/Tabs.vue

Resolved value
"horizontal"

Source

Tabs.vue:19

packages/ui/src/components/tabs/Tabs.vue

class
string | undefined
undefined
Custom CSS classes applied to the outer container when tabs is provided, or to TabsRoot in composition mode.
Details

Declared type

string | undefined

Default value details

Declaration
undefined

Source: packages/ui/src/components/tabs/Tabs.vue

Resolved value
undefined

Source

Tabs.vue:20

packages/ui/src/components/tabs/Tabs.vue

Tabs — Events
NameSignature or typeDescription
@update:modelValue
[value: string]
Emits the new string value when the active tab changes, also updating internal selection in uncontrolled mode.
Details

Declared type

[value: string]

Source

Tabs.vue

packages/ui/src/components/tabs/Tabs.vue

Tabs — Slots
NameSignature or typeDescription
#header
{}
Content above the tabs in data-driven mode, also rendered when tabs is an empty array.
Details

Declared type

{}

Source

Tabs.vue

packages/ui/src/components/tabs/Tabs.vue

#default
{}
Contains the complete tab structure in composition mode. In data-driven mode, replaces the generated panels and should supply TabsContent components. It is not rendered for an empty tabs array.
Details

Declared type

{}

Source

Tabs.vue

packages/ui/src/components/tabs/Tabs.vue

TabsContent

TabsContent — Props
NameTypeDefaultDescription
value
Required
string
—
The tab value associated with this panel, matching its TabsTrigger value.
Details

Declared type

string

Default value details

Not declared
—

Source

TabsContent.vue:8

packages/ui/src/components/tabs/TabsContent.vue

surface
TabsContentSurface | undefined
"plain"
Surface shell mode: plain for zero-padding fitting (ideal for nested Card), panel for standalone card shell with borders and shadow.
Details

Declared type

TabsContentSurface | undefined

Literal values

  • "panel"
  • "plain"

Referenced types

TabsContentSurface
Type definition — TabsContentSurface
export type TabsContentSurface = NonNullable<TabsContentVariantProps['surface']>

Default value details

Resolved value
"plain"

Source

TabsContent.vue:9

packages/ui/src/components/tabs/TabsContent.vue

forceMount
boolean | undefined
undefined
Keeps the panel mounted for external animation control or to retain the panel instance.
Details

Declared type

boolean | undefined

Literal values

  • false
  • true

Default value details

Resolved value
undefined

Source

TabsContent.vue:10

packages/ui/src/components/tabs/TabsContent.vue

class
string | undefined
undefined
Custom CSS classes merged onto the tab panel.
Details

Declared type

string | undefined

Default value details

Resolved value
undefined

Source

TabsContent.vue:11

packages/ui/src/components/tabs/TabsContent.vue

TabsContent — Slots
NameSignature or typeDescription
#default
{}
The content associated with this tab.
Details

Declared type

{}

Source

TabsContent.vue

packages/ui/src/components/tabs/TabsContent.vue

TabsList

TabsList — Props
NameTypeDefaultDescription
size
"default" | "lg" | "sm" | undefined
"default"
The size variant of the tab list container.
Details

Declared type

NonNullable<"default" | "lg" | "sm" | null | undefined> | undefined

Literal values

  • "default"
  • "lg"
  • "sm"

Default value details

Resolved value
"default"

Source

TabsList.vue:12

packages/ui/src/components/tabs/TabsList.vue

orientation
"horizontal" | "vertical" | undefined
undefined

Runtime fallback:Resolves from this prop, then the parent Tabs orientation, then horizontal.

Overrides the list layout styles and data-orientation without changing the root Tabs keyboard orientation.
Details

Declared type

NonNullable<"vertical" | "horizontal" | null | undefined> | undefined

Literal values

  • "horizontal"
  • "vertical"

Default value details

Resolved value
undefined
Runtime fallback
Resolves from this prop, then the parent Tabs orientation, then horizontal.

Applied by the component under the documented runtime conditions.

Source

TabsList.vue:13

packages/ui/src/components/tabs/TabsList.vue

class
string | undefined
undefined
Custom CSS classes merged onto the tab list container.
Details

Declared type

string | undefined

Default value details

Resolved value
undefined

Source

TabsList.vue:14

packages/ui/src/components/tabs/TabsList.vue

TabsList — Slots
NameSignature or typeDescription
#default
{}
The tab trigger list, typically containing TabsTrigger components.
Details

Declared type

{}

Source

TabsList.vue

packages/ui/src/components/tabs/TabsList.vue

TabsTrigger

TabsTrigger — Props
NameTypeDefaultDescription
value
Required
string
—
The unique string identifier linking this tab to its TabsContent.
Details

Declared type

string

Default value details

Not declared
—

Source

TabsTrigger.vue:11

packages/ui/src/components/tabs/TabsTrigger.vue

disabled
boolean | undefined
false
Disables this tab trigger and prevents user activation.
Details

Declared type

boolean | undefined

Literal values

  • false
  • true

Default value details

Resolved value
false

Source

TabsTrigger.vue:12

packages/ui/src/components/tabs/TabsTrigger.vue

variant
"accent" | "default" | "primary" | "secondary" | "slots" | "success" | undefined
"default"
The trigger visual variant, controlling active-state colors and decoration.
Details

Declared type

NonNullable<"default" | "primary" | "secondary" | "success" | "accent" | "slots" | null | undefined> | undefined

Literal values

  • "accent"
  • "default"
  • "primary"
  • "secondary"
  • "slots"
  • "success"

Default value details

Resolved value
"default"

Source

TabsTrigger.vue:13

packages/ui/src/components/tabs/TabsTrigger.vue

class
string | undefined
undefined
Custom CSS classes merged onto the tab trigger.
Details

Declared type

string | undefined

Default value details

Resolved value
undefined

Source

TabsTrigger.vue:14

packages/ui/src/components/tabs/TabsTrigger.vue

TabsTrigger — Slots
NameSignature or typeDescription
#default
{}
Text, icons, or other label content inside the tab trigger.
Details

Declared type

{}

Source

TabsTrigger.vue

packages/ui/src/components/tabs/TabsTrigger.vue

Accessibility ​

  • Keyboard: Arrow keys navigate between tab triggers
  • ARIA Attributes: Tab content is associated with its trigger via ARIA attributes; the active tab has aria-selected="true"

Brute force builds.