๐ข Tabs
Basic
NTabs
are used to navigate between different content and also they have robust focus management and keyboard navigation support.
We'll never share your email with anyone else.
Variant and Color
tabs="{variant}-{color}"
is used to set the variant of the tabs. The default variant is soft-black
.
Prop | Description |
---|---|
tabs | Set the tabs variant and color. |
_tabsTrigger.tabs | Set the tabs variant and color via _tabsTrigger . |
NTabs
is wrapped around the NButton component. This means that all the props and slots of NButton
are available through the _tabsTrigger
prop.We'll never share your email with anyone else.
Disabled
disabled="{boolean}"
is used to disable the tabs. The default value is false
.
Prop | Description |
---|---|
disabled | Set the tabs disabled. |
_tabsTrigger.disabled | Set the tabs disabled via _tabsTrigger . |
or
Size
Prop | Description |
---|---|
size | Set the tabs size. |
_tabsTrigger.size | Set the trigger size. |
_tabsContent.size | Set the content size. |
๐ You can freely adjust the size of the tabs using any size imaginable. No limits exist, and you aan use
breakpoints
such assm:sm, xs:lg
to change size based on screen size orstates
such ashover:lg, focus:3xl
to change size based on input state and more.
The
height
and width
of the tabs scale depends on the tabs-size
. If you want to change the height
and width
simultaneously, you can always customize it using utility classes.Tab 1 content
Tab 2 content
Props
import type { TabsContentProps, TabsListProps, TabsRootProps, TabsTriggerProps } from 'radix-vue'
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, 'tabs' | 'disabled'> {
/**
* The array of items that is passed to tabs.
*
* @default []
*/
items: any[]
// sub-components
_tabsContent?: Partial<NTabsContentProps>
_tabsTrigger?: Partial<NTabsTriggerProps>
_tabsList?: Partial<NTabsListProps>
}
export interface NTabsRootProps extends TabsRootProps, BaseExtensions {
/**
* `UnaUI` preset configuration
*
* @see https://github.com/una-ui/una-ui/blob/main/packages/preset/src/_shortcuts/tabs.ts
*/
una?: {
// components
tabsRoot?: HTMLAttributes['class']
}
}
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?: {
// components
tabsList?: HTMLAttributes['class']
}
}
export interface NTabsTriggerProps extends TabsTriggerProps, Omit<NButtonProps, 'una' | 'size'>, BaseExtensions {
/**
* Allows you to add `UnaUI` button preset properties,
* Think of it as a shortcut for adding options or variants to the preset if available.
*
* @see https://github.com/una-ui/una-ui/blob/main/packages/preset/src/_shortcuts/tabs.ts
* @example
* tabs="solid-green"
*/
tabs?: string
/**
* `UnaUI` preset configuration
*
* @see https://github.com/una-ui/una-ui/blob/main/packages/preset/src/_shortcuts/tabs.ts
*/
una?: {
// components
tabsTrigger?: HTMLAttributes['class']
tabsDefaultVariant?: HTMLAttributes['class']
} & 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?: {
// components
tabsContent?: HTMLAttributes['class']
}
}
Presets
type TabsPrefix = 'tabs'
export const staticTabs: Record<`${TabsPrefix}-${string}` | TabsPrefix, string> = {
// configurations
'tabs': 'transition-colors duration-200 ease-out',
'tabs-default-variant': 'tabs-soft-black',
'tabs-disabled': 'n-disabled',
// components
'tabs-root': 'flex flex-col w-full',
'tabs-trigger': 'w-full focus-visible:z-10',
'tabs-list': 'flex bg-muted items-center justify-center rounded-md p-1 w-full',
'tabs-content': 'mt-4 text-base',
}
export const dynamicTabs = [
[/^tabs-([^-]+)-([^-]+)$/, ([, v = 'solid', c = 'primary']) => `data-[state=active]:btn-${v}-${c}`],
]
export const tabs = [
...dynamicTabs,
staticTabs,
]
Component
<script setup lang="ts">
import type { TabsRootEmits } from 'radix-vue'
import type { NTabsProps } from '../../../types/tabs'
import { useForwardPropsEmits } from 'radix-vue'
import { computed } from 'vue'
import { omitProps } from '../../../utils'
import TabsContent from './TabsContent.vue'
import TabsList from './TabsList.vue'
import TabsRoot from './TabsRoot.vue'
import TabsTrigger from './TabsTrigger.vue'
const props = defineProps<NTabsProps>()
const emits = defineEmits<TabsRootEmits>()
const delegatedProps = computed(() => {
const { class: _, ...delegated } = props
return delegated
})
const forwarded = useForwardPropsEmits(delegatedProps, emits)
</script>
<template>
<TabsRoot
v-bind="omitProps(forwarded, ['items', 'tabs', 'disabled'])"
:default-value="defaultValue"
>
<TabsList v-bind="forwarded._tabsList">
<slot name="list" :items="items">
<template
v-for="item in items"
:key="item.value"
>
<TabsTrigger
:tabs="item?._tabsTrigger?.tabs || item.tabs || props.tabs"
:disabled="item?._tabsTrigger?.disabled ?? item.disabled ?? props.disabled"
:value="item.value"
v-bind="{ ...forwarded._tabsTrigger, ...item?._tabsTrigger }"
>
<slot name="trigger" :item="item" :disabled="item?._tabsTrigger?.disabled ?? item.disabled ?? props.disabled ?? false">
{{ item.name }}
</slot>
</TabsTrigger>
</template>
</slot>
</TabsList>
<template
v-for="item in items"
:key="item.value"
>
<TabsContent v-bind="forwarded._tabsContent" :value="item.value">
<slot name="content" :item="item">
<component :is="typeof item.content === 'string' ? 'span' : item.content">
{{ typeof item.content === 'string' ? item.content : '' }}
</component>
</slot>
</TabsContent>
</template>
</TabsRoot>
</template>