Tabs
A set of layered sections of content—known as tab panels—that are displayed one at a time.
Examples
Basic
Prop | Default | Type | Description |
---|---|---|---|
content | - | string | Set the tabs content. |
disabled | - | boolean | Set to disable the tabs. |
Preview
Code
We'll never share your email with anyone else.
Read more in Reka Tabs Root API.
Variant and Color
Prop | Default | Type | Description |
---|---|---|---|
tabs-active | soft-black | string | Controls the appearance of active tabs by setting variant and color. |
tabs-inactive | - | string | Defines the variant and color styling for inactive tabs. |
_tabsTrigger.tabs-active | soft-black | string | Overrides the active tab styling at the individual trigger level. |
_tabsTrigger.tabs-inactive | - | string | Overrides the inactive tab styling at the individual trigger level. |
Preview
Code
We'll never share your email with anyone else.
Read more in Button Colors
Disabled
Prop | Default | Type | Description |
---|---|---|---|
disabled | false | boolean | Set the tabs disabled. |
_tabsTrigger.disabled | - | boolean | Set the tabs disabled via _tabsTrigger . |
Preview
Code
or
Size
Prop | Default | Type | Description |
---|---|---|---|
size | sm | string | Set the tabs size. |
_tabsTrigger.size | sm | string | Set the trigger size. |
Preview
Code
Tab 1 content
Tab 1 content
Tab 1 content
Tab 2 content
Read more in Button Size
Slots
Name | Props | Description |
---|---|---|
default | - | Allows advanced customization using sub-components, replacing the default tabs structure. |
list | items | The container for tab triggers/buttons that users can click to switch between tabs. |
trigger | value | The clickable tab button that activates its corresponding content panel. |
content | value | The content panel that displays when its corresponding trigger is selected. |
Custom Rendering
Use the default
slot for full control over the tabs's structure. This allows you to compose the tabs using its individual sub-components (like TabsList
, TabsTrigger
, etc., listed in the Components section), similar to libraries like shadcn/ui
.
Preview
Code
Account
Make changes to your account here. Click save when you're done.
Presets
shortcuts/tabs.ts
type TabsPrefix = 'tabs'
export const staticTabs: Record<`${TabsPrefix}-${string}` | TabsPrefix, string> = {
// configurations
'tabs': 'flex flex-col gap-2',
'tabs-disabled': 'n-disabled',
// components
'tabs-trigger': 'py-0.25em h-[calc(100%-1px)]',
'tabs-list': 'bg-muted text-muted inline-flex h-2.5714285714285716em w-fit items-center justify-center rounded-lg p-[3px]',
'tabs-content': 'flex-1 outline-none',
}
export const dynamicTabs = [
[/^tabs-active-([^-]+)-([^-]+)$/, ([, v = 'solid', c = 'primary']) => `data-[state=active]:btn-${v}-${c}`],
[/^tabs-inactive-([^-]+)-([^-]+)$/, ([, v = 'solid', c = 'primary']) => `data-[state=inactive]:btn-${v}-${c}`],
]
export const tabs = [
...dynamicTabs,
staticTabs,
]
Props
types/tabs.ts
import type { TabsContentProps, TabsListProps, TabsRootProps, TabsTriggerProps } from 'reka-ui'
import type { HTMLAttributes } from 'vue'
import type { NButtonProps } from './button'
interface BaseExtensions {
class?: HTMLAttributes['class']
size?: HTMLAttributes['class']
}
export interface NTabsProps extends TabsRootProps, BaseExtensions, Pick<NTabsTriggerProps, 'tabsActive' | 'tabsInactive' | 'disabled'> {
/**
* The array of items that is passed to tabs.
*
* @default []
*/
items?: any[]
// sub-components
_tabsContent?: Partial<NTabsContentProps>
_tabsTrigger?: Partial<NTabsTriggerProps>
_tabsList?: Partial<NTabsListProps>
una?: NTabsUnaProps
}
export interface NTabsListProps extends TabsListProps, BaseExtensions {
/**
* `UnaUI` preset configuration
*
* @see https://github.com/una-ui/una-ui/blob/main/packages/preset/src/_shortcuts/tabs.ts
*/
una?: Pick<NTabsUnaProps, 'tabsList'>
}
export interface NTabsTriggerProps extends TabsTriggerProps, Omit<NButtonProps, 'una'> {
una?: Pick<NTabsUnaProps, 'tabsTrigger'> & Pick<NButtonProps, 'una'>
}
export interface NTabsContentProps extends TabsContentProps, BaseExtensions {
/**
* `UnaUI` preset configuration
*
* @see https://github.com/una-ui/una-ui/blob/main/packages/preset/src/_shortcuts/tabs.ts
*/
una?: Pick<NTabsUnaProps, 'tabsContent'>
}
export interface NTabsUnaProps {
tabs?: HTMLAttributes['class']
tabsList?: HTMLAttributes['class']
tabsTrigger?: HTMLAttributes['class']
tabsContent?: HTMLAttributes['class']
}
Components
Tabs.vue
TabsList.vue
TabsTrigger.vue
TabsContent.vue
<script setup lang="ts">
import type { TabsRootEmits } from 'reka-ui'
import type { NTabsProps } from '../../../types/tabs'
import { reactiveOmit } from '@vueuse/core'
import { TabsRoot, useForwardPropsEmits } from 'reka-ui'
import { cn } from '../../../utils'
import TabsContent from './TabsContent.vue'
import TabsList from './TabsList.vue'
import TabsTrigger from './TabsTrigger.vue'
const props = withDefaults(defineProps<NTabsProps>(), {
size: 'sm',
})
const emits = defineEmits<TabsRootEmits>()
const delegatedProps = reactiveOmit(props, ['class', 'items', 'tabsActive', 'tabsInactive', 'disabled', 'size', 'una'])
const forwarded = useForwardPropsEmits(delegatedProps, emits)
</script>
<template>
<TabsRoot
v-bind="forwarded"
:class="cn(
'tabs',
props.una?.tabs,
props.class,
)"
>
<slot>
<TabsList
v-bind="forwarded._tabsList"
:una
:size
>
<slot name="list" :items="items">
<template
v-for="item in items"
:key="item.value"
>
<TabsTrigger
:tabs-active="item?._tabsTrigger?.tabsActive || item.tabsActive || props.tabsActive"
:tabs-inactive="item?._tabsTrigger?.tabsInactive || item.tabsInactive || props.tabsInactive"
:disabled="item?._tabsTrigger?.disabled || item.disabled || props.disabled"
:value="item.value"
:size
v-bind="{ ...forwarded._tabsTrigger, ...item?._tabsTrigger }"
:una
>
<slot name="trigger" :item="item" :disabled="item?._tabsTrigger?.disabled || item.disabled || props.disabled">
{{ item.name }}
</slot>
</TabsTrigger>
</template>
</slot>
</TabsList>
<template
v-for="item in items"
:key="item.value"
>
<TabsContent
v-bind="forwarded._tabsContent"
:value="item.value"
:una
>
<slot name="content" :item="item">
<component :is="typeof item.content === 'string' ? 'span' : item.content">
{{ typeof item.content === 'string' ? item.content : '' }}
</component>
</slot>
</TabsContent>
</template>
</slot>
</TabsRoot>
</template>