NavigationMenu
Usage
Items
Use the items
prop as an array of objects with the following properties:
label?: string
icon?: string
avatar?: AvatarProps
badge?: string | number | BadgeProps
trailingIcon?: string
value?: string
disabled?: boolean
class?: any
slot?: string
onSelect?(e: Event): void
You can also pass any property from the Link component such as to
, target
, etc.
<script setup lang="ts">
const items = ref([
{
label: 'Guide',
icon: 'i-lucide-book-open',
to: '/getting-started',
children: [
{
label: 'Introduction',
description: 'Fully styled and customizable components for Nuxt.',
icon: 'i-lucide-house'
},
{
label: 'Installation',
description: 'Learn how to install and configure Nuxt UI in your application.',
icon: 'i-lucide-cloud-download'
},
{
label: 'Icons',
icon: 'i-lucide-smile',
description: 'You have nothing to do, @nuxt/icon will handle it automatically.'
},
{
label: 'Colors',
icon: 'i-lucide-swatch-book',
description: 'Choose a primary and a neutral color from your Tailwind CSS theme.'
},
{
label: 'Theme',
icon: 'i-lucide-cog',
description: 'You can customize components by using the `class` / `ui` props or in your app.config.ts.'
}
]
},
{
label: 'Composables',
icon: 'i-lucide-database',
to: '/composables',
children: [
{
label: 'defineShortcuts',
icon: 'i-lucide-file-text',
description: 'Define shortcuts for your application.',
to: '/composables/define-shortcuts'
},
{
label: 'useModal',
icon: 'i-lucide-file-text',
description: 'Display a modal within your application.',
to: '/composables/use-modal'
},
{
label: 'useSlideover',
icon: 'i-lucide-file-text',
description: 'Display a slideover within your application.',
to: '/composables/use-slideover'
},
{
label: 'useToast',
icon: 'i-lucide-file-text',
description: 'Display a toast within your application.',
to: '/composables/use-toast'
}
]
},
{
label: 'Components',
icon: 'i-lucide-box',
to: '/components',
active: true,
children: [
{
label: 'Link',
icon: 'i-lucide-file-text',
description: 'Use NuxtLink with superpowers.',
to: '/components/link'
},
{
label: 'Modal',
icon: 'i-lucide-file-text',
description: 'Display a modal within your application.',
to: '/components/modal'
},
{
label: 'NavigationMenu',
icon: 'i-lucide-file-text',
description: 'Display a list of links.',
to: '/components/navigation-menu'
},
{
label: 'Pagination',
icon: 'i-lucide-file-text',
description: 'Display a list of pages.',
to: '/components/pagination'
},
{
label: 'Popover',
icon: 'i-lucide-file-text',
description: 'Display a non-modal dialog that floats around a trigger element.',
to: '/components/popover'
},
{
label: 'Progress',
icon: 'i-lucide-file-text',
description: 'Show a horizontal bar to indicate task progression.',
to: '/components/progress'
}
]
},
{
label: 'GitHub',
icon: 'i-simple-icons-github',
badge: '3.8k',
to: 'https://github.com/nuxt/ui',
target: '_blank'
},
{
label: 'Help',
icon: 'i-lucide-circle-help',
disabled: true
}
])
</script>
<template>
<UNavigationMenu :items="items" class="justify-center" />
</template>
items
prop to display groups of items.children
array of objects with the following properties to create submenus:label: string
description?: string
icon?: string
class?: any
onSelect?(e: Event): void
Orientation
Use the orientation
prop to change the orientation of the NavigationMenu.
When orientation is vertical
, a Collapsible component is used to display children. You can control the open state of each item using the open
and defaultOpen
properties.
<script setup lang="ts">
const items = ref([
[
{
label: 'Guide',
icon: 'i-lucide-book-open',
defaultOpen: true,
children: [
{
label: 'Introduction',
description: 'Fully styled and customizable components for Nuxt.',
icon: 'i-lucide-house'
},
{
label: 'Installation',
description: 'Learn how to install and configure Nuxt UI in your application.',
icon: 'i-lucide-cloud-download'
},
{
label: 'Icons',
icon: 'i-lucide-smile',
description: 'You have nothing to do, @nuxt/icon will handle it automatically.'
},
{
label: 'Colors',
icon: 'i-lucide-swatch-book',
description: 'Choose a primary and a neutral color from your Tailwind CSS theme.'
},
{
label: 'Theme',
icon: 'i-lucide-cog',
description: 'You can customize components by using the `class` / `ui` props or in your app.config.ts.'
}
]
},
{
label: 'Composables',
icon: 'i-lucide-database',
children: [
{
label: 'defineShortcuts',
icon: 'i-lucide-file-text',
description: 'Define shortcuts for your application.',
to: '/composables/define-shortcuts'
},
{
label: 'useModal',
icon: 'i-lucide-file-text',
description: 'Display a modal within your application.',
to: '/composables/use-modal'
},
{
label: 'useSlideover',
icon: 'i-lucide-file-text',
description: 'Display a slideover within your application.',
to: '/composables/use-slideover'
},
{
label: 'useToast',
icon: 'i-lucide-file-text',
description: 'Display a toast within your application.',
to: '/composables/use-toast'
}
]
},
{
label: 'Components',
icon: 'i-lucide-box',
active: true,
children: [
{
label: 'Link',
icon: 'i-lucide-file-text',
description: 'Use NuxtLink with superpowers.',
to: '/components/link'
},
{
label: 'Modal',
icon: 'i-lucide-file-text',
description: 'Display a modal within your application.',
to: '/components/modal'
},
{
label: 'NavigationMenu',
icon: 'i-lucide-file-text',
description: 'Display a list of links.',
to: '/components/navigation-menu'
},
{
label: 'Pagination',
icon: 'i-lucide-file-text',
description: 'Display a list of pages.',
to: '/components/pagination'
},
{
label: 'Popover',
icon: 'i-lucide-file-text',
description: 'Display a non-modal dialog that floats around a trigger element.',
to: '/components/popover'
},
{
label: 'Progress',
icon: 'i-lucide-file-text',
description: 'Show a horizontal bar to indicate task progression.',
to: '/components/progress'
}
]
}
],
[
{
label: 'GitHub',
icon: 'i-simple-icons-github',
badge: '3.8k',
to: 'https://github.com/nuxt/ui',
target: '_blank'
},
{
label: 'Help',
icon: 'i-lucide-circle-help',
disabled: true
}
]
])
</script>
<template>
<UNavigationMenu orientation="vertical" :items="items" class="data-[orientation=vertical]:w-48" />
</template>
horizontal
and separated when orientation is vertical
.Highlight
Use the highlight
prop to display a highlighted border for the active item.
Use the highlight-color
prop to change the color of the border. It defaults to the color
prop.
<script setup lang="ts">
const items = ref([
[
{
label: 'Guide',
icon: 'i-lucide-book-open',
to: '/getting-started'
},
{
label: 'Composables',
icon: 'i-lucide-database',
to: '/composables'
},
{
label: 'Components',
icon: 'i-lucide-box',
to: '/components',
active: true
}
],
[
{
label: 'GitHub',
icon: 'i-simple-icons-github',
badge: '3.8k',
to: 'https://github.com/nuxt/ui',
target: '_blank'
}
]
])
</script>
<template>
<UNavigationMenu
highlight
orientation="horizontal"
:items="items"
class="data-[orientation=horizontal]:border-b data-[orientation=vertical]:border-l border-[var(--ui-border)]"
/>
</template>
border-l
and border-b
classes are applied to display a border, this is not done by default to let you have a clean slate to work with.Color
Use the color
prop to change the color of the NavigationMenu.
<script setup lang="ts">
const items = ref([
[
{
label: 'Guide',
icon: 'i-lucide-book-open',
to: '/getting-started'
},
{
label: 'Composables',
icon: 'i-lucide-database',
to: '/composables'
},
{
label: 'Components',
icon: 'i-lucide-box',
to: '/components',
active: true
}
],
[
{
label: 'GitHub',
icon: 'i-simple-icons-github',
badge: '3.8k',
to: 'https://github.com/nuxt/ui',
target: '_blank'
}
]
])
</script>
<template>
<UNavigationMenu color="neutral" :items="items" />
</template>
Variant
Use the variant
prop to change the variant of the NavigationMenu.
<script setup lang="ts">
const items = ref([
[
{
label: 'Guide',
icon: 'i-lucide-book-open',
to: '/getting-started'
},
{
label: 'Composables',
icon: 'i-lucide-database',
to: '/composables'
},
{
label: 'Components',
icon: 'i-lucide-box',
to: '/components',
active: true
}
],
[
{
label: 'GitHub',
icon: 'i-simple-icons-github',
badge: '3.8k',
to: 'https://github.com/nuxt/ui',
target: '_blank'
}
]
])
</script>
<template>
<UNavigationMenu color="neutral" variant="link" :items="items" />
</template>
highlight
prop changes the pill
variant active item style. Try it out to see the difference.Trailing Icon
Use the trailing-icon
prop to customize the trailing Icon of each item. Defaults to i-lucide-chevron-down
. This icon is only displayed when an item has children.
trailingIcon
property in the item object.<script setup lang="ts">
const items = ref([
{
label: 'Guide',
icon: 'i-lucide-book-open',
to: '/getting-started',
children: [
{
label: 'Introduction',
description: 'Fully styled and customizable components for Nuxt.',
icon: 'i-lucide-house'
},
{
label: 'Installation',
description: 'Learn how to install and configure Nuxt UI in your application.',
icon: 'i-lucide-cloud-download'
},
{
label: 'Icons',
icon: 'i-lucide-smile',
description: 'You have nothing to do, @nuxt/icon will handle it automatically.'
},
{
label: 'Colors',
icon: 'i-lucide-swatch-book',
description: 'Choose a primary and a neutral color from your Tailwind CSS theme.'
},
{
label: 'Theme',
icon: 'i-lucide-cog',
description: 'You can customize components by using the `class` / `ui` props or in your app.config.ts.'
}
]
},
{
label: 'Composables',
icon: 'i-lucide-database',
to: '/composables',
children: [
{
label: 'defineShortcuts',
icon: 'i-lucide-file-text',
description: 'Define shortcuts for your application.',
to: '/composables/define-shortcuts'
},
{
label: 'useModal',
icon: 'i-lucide-file-text',
description: 'Display a modal within your application.',
to: '/composables/use-modal'
},
{
label: 'useSlideover',
icon: 'i-lucide-file-text',
description: 'Display a slideover within your application.',
to: '/composables/use-slideover'
},
{
label: 'useToast',
icon: 'i-lucide-file-text',
description: 'Display a toast within your application.',
to: '/composables/use-toast'
}
]
},
{
label: 'Components',
icon: 'i-lucide-box',
to: '/components',
active: true,
children: [
{
label: 'Link',
icon: 'i-lucide-file-text',
description: 'Use NuxtLink with superpowers.',
to: '/components/link'
},
{
label: 'Modal',
icon: 'i-lucide-file-text',
description: 'Display a modal within your application.',
to: '/components/modal'
},
{
label: 'NavigationMenu',
icon: 'i-lucide-file-text',
description: 'Display a list of links.',
to: '/components/navigation-menu'
},
{
label: 'Pagination',
icon: 'i-lucide-file-text',
description: 'Display a list of pages.',
to: '/components/pagination'
},
{
label: 'Popover',
icon: 'i-lucide-file-text',
description: 'Display a non-modal dialog that floats around a trigger element.',
to: '/components/popover'
},
{
label: 'Progress',
icon: 'i-lucide-file-text',
description: 'Show a horizontal bar to indicate task progression.',
to: '/components/progress'
}
]
}
])
</script>
<template>
<UNavigationMenu trailing-icon="i-lucide-arrow-down" :items="items" class="justify-center" />
</template>
Arrow
Use the arrow
prop to display an arrow on the NavigationMenu content when items have children.
<script setup lang="ts">
const items = ref([
{
label: 'Guide',
icon: 'i-lucide-book-open',
to: '/getting-started',
children: [
{
label: 'Introduction',
description: 'Fully styled and customizable components for Nuxt.',
icon: 'i-lucide-house'
},
{
label: 'Installation',
description: 'Learn how to install and configure Nuxt UI in your application.',
icon: 'i-lucide-cloud-download'
},
{
label: 'Icons',
icon: 'i-lucide-smile',
description: 'You have nothing to do, @nuxt/icon will handle it automatically.'
},
{
label: 'Colors',
icon: 'i-lucide-swatch-book',
description: 'Choose a primary and a neutral color from your Tailwind CSS theme.'
},
{
label: 'Theme',
icon: 'i-lucide-cog',
description: 'You can customize components by using the `class` / `ui` props or in your app.config.ts.'
}
]
},
{
label: 'Composables',
icon: 'i-lucide-database',
to: '/composables',
children: [
{
label: 'defineShortcuts',
icon: 'i-lucide-file-text',
description: 'Define shortcuts for your application.',
to: '/composables/define-shortcuts'
},
{
label: 'useModal',
icon: 'i-lucide-file-text',
description: 'Display a modal within your application.',
to: '/composables/use-modal'
},
{
label: 'useSlideover',
icon: 'i-lucide-file-text',
description: 'Display a slideover within your application.',
to: '/composables/use-slideover'
},
{
label: 'useToast',
icon: 'i-lucide-file-text',
description: 'Display a toast within your application.',
to: '/composables/use-toast'
}
]
},
{
label: 'Components',
icon: 'i-lucide-box',
to: '/components',
active: true,
children: [
{
label: 'Link',
icon: 'i-lucide-file-text',
description: 'Use NuxtLink with superpowers.',
to: '/components/link'
},
{
label: 'Modal',
icon: 'i-lucide-file-text',
description: 'Display a modal within your application.',
to: '/components/modal'
},
{
label: 'NavigationMenu',
icon: 'i-lucide-file-text',
description: 'Display a list of links.',
to: '/components/navigation-menu'
},
{
label: 'Pagination',
icon: 'i-lucide-file-text',
description: 'Display a list of pages.',
to: '/components/pagination'
},
{
label: 'Popover',
icon: 'i-lucide-file-text',
description: 'Display a non-modal dialog that floats around a trigger element.',
to: '/components/popover'
},
{
label: 'Progress',
icon: 'i-lucide-file-text',
description: 'Show a horizontal bar to indicate task progression.',
to: '/components/progress'
}
]
}
])
</script>
<template>
<UNavigationMenu arrow :items="items" class="justify-center" />
</template>
Examples
Control active item
You can control the active item by using the default-value
prop or the v-model
directive with the index of the item.
<script setup lang="ts">
const items = [
{
label: 'Guide',
icon: 'i-lucide-book-open',
children: [
{
label: 'Introduction',
description: 'Fully styled and customizable components for Nuxt.',
icon: 'i-lucide-house'
},
{
label: 'Installation',
description: 'Learn how to install and configure Nuxt UI in your application.',
icon: 'i-lucide-cloud-download'
},
{
label: 'Icons',
icon: 'i-lucide-smile',
description: 'You have nothing to do, @nuxt/icon will handle it automatically.'
},
{
label: 'Colors',
icon: 'i-lucide-swatch-book',
description: 'Choose a primary and a neutral color from your Tailwind CSS theme.'
},
{
label: 'Theme',
icon: 'i-lucide-cog',
description: 'You can customize components by using the `class` / `ui` props or in your app.config.ts.'
}
]
},
{
label: 'Composables',
icon: 'i-lucide-database',
children: [
{
label: 'defineShortcuts',
icon: 'i-lucide-file-text',
description: 'Define shortcuts for your application.'
},
{
label: 'useModal',
icon: 'i-lucide-file-text',
description: 'Display a modal within your application.'
},
{
label: 'useSlideover',
icon: 'i-lucide-file-text',
description: 'Display a slideover within your application.'
},
{
label: 'useToast',
icon: 'i-lucide-file-text',
description: 'Display a toast within your application.'
}
]
},
{
label: 'Components',
icon: 'i-lucide-box',
children: [
{
label: 'Link',
icon: 'i-lucide-file-text',
description: 'Use NuxtLink with superpowers.'
},
{
label: 'Modal',
icon: 'i-lucide-file-text',
description: 'Display a modal within your application.'
},
{
label: 'NavigationMenu',
icon: 'i-lucide-file-text',
description: 'Display a list of links.'
},
{
label: 'Pagination',
icon: 'i-lucide-file-text',
description: 'Display a list of pages.'
},
{
label: 'Popover',
icon: 'i-lucide-file-text',
description: 'Display a non-modal dialog that floats around a trigger element.'
},
{
label: 'Progress',
icon: 'i-lucide-file-text',
description: 'Show a horizontal bar to indicate task progression.'
}
]
}
]
const active = ref()
defineShortcuts({
1: () => {
active.value = '0'
},
2: () => {
active.value = '1'
},
3: () => {
active.value = '2'
}
})
</script>
<template>
<UNavigationMenu v-model="active" :items="items" class="justify-center" />
</template>
value
of one of the items if provided.With custom slot
Use the slot
property to customize a specific item.
You will have access to the following slots:
#{{ item.slot }}
#{{ item.slot }}-leading
#{{ item.slot }}-label
#{{ item.slot }}-trailing
#{{ item.slot }}-content
<script setup lang="ts">
const items = [
{
label: 'Guide',
icon: 'i-lucide-book-open'
},
{
label: 'Composables',
icon: 'i-lucide-database'
},
{
label: 'Components',
icon: 'i-lucide-box',
slot: 'components'
}
]
</script>
<template>
<UNavigationMenu :items="items" class="justify-center">
<template #components-trailing>
<UBadge label="44" variant="subtle" size="sm" />
</template>
</UNavigationMenu>
</template>
#item
, #item-leading
, #item-label
, #item-trailing
and #item-content
slots to customize all items.With content slot
Use the #item-content
slot or the slot
property (#{{ item.slot }}-content
) to customize the content of a specific item.
<script setup lang="ts">
const items = [
{
label: 'Docs',
icon: 'i-lucide-book-open',
slot: 'docs',
children: [
{
label: 'Icons',
description: 'You have nothing to do, @nuxt/icon will handle it automatically.'
},
{
label: 'Colors',
description: 'Choose a primary and a neutral color from your Tailwind CSS theme.'
},
{
label: 'Theme',
description: 'You can customize components by using the `class` / `ui` props or in your app.config.ts.'
}
]
},
{
label: 'Components',
icon: 'i-lucide-box',
slot: 'components',
children: [
{
label: 'Link',
description: 'Use NuxtLink with superpowers.'
},
{
label: 'Modal',
description: 'Display a modal within your application.'
},
{
label: 'NavigationMenu',
description: 'Display a list of links.'
},
{
label: 'Pagination',
description: 'Display a list of pages.'
},
{
label: 'Popover',
description: 'Display a non-modal dialog that floats around a trigger element.'
},
{
label: 'Progress',
description: 'Show a horizontal bar to indicate task progression.'
}
]
},
{
label: 'GitHub'
}
]
</script>
<template>
<UNavigationMenu
:items="items"
class="justify-center"
:ui="{
viewport: 'sm:w-[var(--radix-navigation-menu-viewport-width)]',
childList: 'sm:w-96',
childLinkDescription: 'text-balance line-clamp-2'
}"
>
<template #docs-content="{ item }">
<ul class="grid gap-2 p-4 lg:w-[500px] lg:grid-cols-[minmax(0,.75fr)_minmax(0,1fr)]">
<li class="row-span-3">
<Placeholder class="size-full min-h-48" />
</li>
<li v-for="child in item.children" :key="child.label">
<ULink class="text-sm text-left rounded-md p-3 transition-colors hover:bg-[var(--ui-bg-elevated)]/50">
<p class="font-medium text-[var(--ui-text-highlighted)]">
{{ child.label }}
</p>
<p class="text-[var(--ui-text-muted)] line-clamp-2">
{{ child.description }}
</p>
</ULink>
</li>
</ul>
</template>
</UNavigationMenu>
</template>
sm:w-[var(--radix-navigation-menu-viewport-width)]
class on the viewport
to have a dynamic width. This requires to set a width on the content's first child.API
Props
Prop | Default | Type |
---|---|---|
as |
|
The element or component this component should render as. |
trailingIcon |
|
The icon displayed to open the menu. |
items |
| |
color |
|
|
variant |
|
|
orientation |
|
The orientation of the menu. |
highlight |
Display a line next to the active item. | |
highlightColor |
|
|
content |
The content of the menu. | |
arrow |
|
Display an arrow alongside the menu. |
labelKey |
|
The key used to get the label from the item. |
delayDuration |
|
The duration from when the pointer enters the trigger until the tooltip gets opened. |
skipDelayDuration |
|
How much time a user has to enter another trigger without incurring a delay again. |
defaultValue |
The value of the menu item that should be active when initially rendered. Use when you do not need to control the value state. | |
modelValue |
The controlled value of the menu item to activate. Can be used as | |
disableClickTrigger |
|
If |
disableHoverTrigger |
|
If |
ui |
|
Slots
Slot | Type |
---|---|
item |
|
item-leading |
|
item-label |
|
item-trailing |
|
item-content |
|
Emits
Event | Type |
---|---|
update:modelValue |
|
Theme
export default defineAppConfig({
ui: {
navigationMenu: {
slots: {
root: 'relative flex gap-1.5 [&>div]:min-w-0',
list: 'isolate min-w-0',
item: 'min-w-0',
link: 'group relative w-full flex items-center gap-1.5 font-medium text-sm before:absolute before:z-[-1] before:rounded-[calc(var(--ui-radius)*1.5)] focus:outline-none focus-visible:outline-none dark:focus-visible:outline-none focus-visible:before:ring-inset focus-visible:before:ring-2',
linkLeadingIcon: 'shrink-0 size-5',
linkLeadingAvatar: 'shrink-0',
linkLeadingAvatarSize: '2xs',
linkTrailing: 'ms-auto inline-flex',
linkTrailingBadge: 'shrink-0 rounded-[calc(var(--ui-radius)]',
linkTrailingBadgeSize: 'sm',
linkTrailingIcon: 'size-5 transform shrink-0 group-data-[state=open]:rotate-180 transition-transform duration-200',
linkLabel: 'truncate',
linkLabelExternalIcon: 'inline-block size-3 align-top text-[var(--ui-text-dimmed)]',
childList: '',
childItem: '',
childLink: 'group size-full px-3 py-2 rounded-[calc(var(--ui-radius)*1.5)] flex items-start gap-2 text-start',
childLinkWrapper: 'flex flex-col items-start',
childLinkIcon: 'size-5 shrink-0',
childLinkLabel: 'font-semibold text-sm relative inline-flex',
childLinkLabelExternalIcon: 'inline-block size-3 align-top text-[var(--ui-text-dimmed)]',
childLinkDescription: 'text-sm text-[var(--ui-text-muted)]',
separator: 'px-2 h-px bg-[var(--ui-border)]',
viewportWrapper: 'absolute top-full left-0 flex w-full justify-center',
viewport: 'relative overflow-hidden bg-[var(--ui-bg)] shadow-lg rounded-[calc(var(--ui-radius)*1.5)] ring ring-[var(--ui-border)] h-[var(--radix-navigation-menu-viewport-height)] w-full transition-[width,height] origin-[top_center] data-[state=open]:animate-[scale-in_100ms_ease-out] data-[state=closed]:animate-[scale-out_100ms_ease-in]',
content: 'absolute top-0 left-0 w-full data-[motion=from-start]:animate-[enter-from-left_200ms_ease] data-[motion=from-end]:animate-[enter-from-right_200ms_ease] data-[motion=to-start]:animate-[exit-to-left_200ms_ease] data-[motion=to-end]:animate-[exit-to-right_200ms_ease]',
indicator: 'data-[state=visible]:animate-[fade-in_100ms_ease-out] data-[state=hidden]:animate-[fade-out_100ms_ease-in] bottom-0 z-[1] flex h-2.5 items-end justify-center overflow-hidden transition-transform duration-200 ease-out',
arrow: 'relative top-[50%] size-2.5 rotate-45 border border-[var(--ui-border)] bg-[var(--ui-bg)] z-[1] rounded-[calc(var(--ui-radius)/2)]'
},
variants: {
color: {
primary: {
link: 'focus-visible:before:ring-[var(--ui-primary)]',
childLink: 'focus-visible:outline-[var(--ui-primary)]'
},
secondary: {
link: 'focus-visible:before:ring-[var(--ui-secondary)]',
childLink: 'focus-visible:outline-[var(--ui-secondary)]'
},
success: {
link: 'focus-visible:before:ring-[var(--ui-success)]',
childLink: 'focus-visible:outline-[var(--ui-success)]'
},
info: {
link: 'focus-visible:before:ring-[var(--ui-info)]',
childLink: 'focus-visible:outline-[var(--ui-info)]'
},
warning: {
link: 'focus-visible:before:ring-[var(--ui-warning)]',
childLink: 'focus-visible:outline-[var(--ui-warning)]'
},
error: {
link: 'focus-visible:before:ring-[var(--ui-error)]',
childLink: 'focus-visible:outline-[var(--ui-error)]'
},
neutral: {
link: 'focus-visible:before:ring-[var(--ui-border-inverted)]',
childLink: 'focus-visible:outline-[var(--ui-border-inverted)]'
}
},
highlightColor: {
primary: '',
secondary: '',
success: '',
info: '',
warning: '',
error: '',
neutral: ''
},
variant: {
pill: '',
link: ''
},
orientation: {
horizontal: {
root: 'w-full items-center justify-between',
list: 'flex items-center',
item: 'py-2',
link: 'px-2.5 py-1.5 before:inset-x-px before:inset-y-0',
childList: 'grid grid-cols-2 gap-2 p-2'
},
vertical: {
root: 'flex-col',
link: 'flex-row px-2.5 py-1.5 before:inset-y-px before:inset-x-0',
childList: 'ms-5 border-s border-[var(--ui-border)]',
childItem: 'ps-1.5 -ms-px'
}
},
active: {
true: {
childLink: 'bg-[var(--ui-bg-elevated)] text-[var(--ui-text-highlighted)]',
childLinkIcon: 'text-[var(--ui-text)]'
},
false: {
link: 'text-[var(--ui-text-muted)]',
linkLeadingIcon: 'text-[var(--ui-text-dimmed)]',
childLink: [
'hover:bg-[var(--ui-bg-elevated)]/50 text-[var(--ui-text)] hover:text-[var(--ui-text-highlighted)]',
'transition-colors'
],
childLinkIcon: [
'text-[var(--ui-text-dimmed)] group-hover:text-[var(--ui-text)]',
'transition-colors'
]
}
},
disabled: {
true: {
link: 'cursor-not-allowed opacity-75'
}
},
highlight: {
true: ''
}
},
compoundVariants: [
{
highlight: true,
orientation: 'horizontal',
class: {
item: '-mb-px',
link: 'after:absolute after:-bottom-2 after:inset-x-2.5 after:block after:h-px after:rounded-full'
}
},
{
highlight: true,
orientation: 'vertical',
class: {
item: 'px-1.5 -ms-px',
link: 'after:absolute after:-start-1.5 after:inset-y-0.5 after:block after:w-px after:rounded-full'
}
},
{
disabled: false,
active: false,
variant: 'pill',
class: {
link: [
'hover:text-[var(--ui-text-highlighted)] hover:before:bg-[var(--ui-bg-elevated)]/50 data-[state=open]:text-[var(--ui-text-highlighted)]',
'transition-colors before:transition-colors'
],
linkLeadingIcon: [
'group-hover:text-[var(--ui-text)] group-data-[state=open]:text-[var(--ui-text)]',
'transition-colors'
]
}
},
{
disabled: false,
variant: 'pill',
highlight: true,
orientation: 'horizontal',
class: {
link: 'data-[state=open]:before:bg-[var(--ui-bg-elevated)]/50'
}
},
{
disabled: false,
variant: 'pill',
highlight: false,
active: false,
orientation: 'horizontal',
class: {
link: 'data-[state=open]:before:bg-[var(--ui-bg-elevated)]/50'
}
},
{
color: 'primary',
variant: 'pill',
active: true,
class: {
link: 'text-[var(--ui-primary)]',
linkLeadingIcon: 'text-[var(--ui-primary)]'
}
},
{
color: 'neutral',
variant: 'pill',
active: true,
class: {
link: 'text-[var(--ui-text-highlighted)]',
linkLeadingIcon: 'text-[var(--ui-text-highlighted)]'
}
},
{
variant: 'pill',
active: true,
highlight: false,
class: {
link: 'before:bg-[var(--ui-bg-elevated)]'
}
},
{
variant: 'pill',
active: true,
highlight: true,
class: {
link: [
'hover:before:bg-[var(--ui-bg-elevated)]/50',
'before:transition-colors'
]
}
},
{
disabled: false,
active: false,
variant: 'link',
class: {
link: [
'hover:text-[var(--ui-text-highlighted)] data-[state=open]:text-[var(--ui-text-highlighted)]',
'transition-colors'
],
linkLeadingIcon: [
'group-hover:text-[var(--ui-text)] group-data-[state=open]:text-[var(--ui-text)]',
'transition-colors'
]
}
},
{
color: 'primary',
variant: 'link',
active: true,
class: {
link: 'text-[var(--ui-primary)]',
linkLeadingIcon: 'text-[var(--ui-primary)]'
}
},
{
color: 'neutral',
variant: 'link',
active: true,
class: {
link: 'text-[var(--ui-text-highlighted)]',
linkLeadingIcon: 'text-[var(--ui-text-highlighted)]'
}
},
{
highlightColor: 'primary',
highlight: true,
active: true,
class: {
link: 'after:bg-[var(--ui-primary)]'
}
},
{
highlightColor: 'neutral',
highlight: true,
active: true,
class: {
link: 'after:bg-[var(--ui-bg-inverted)]'
}
}
],
defaultVariants: {
color: 'primary',
highlightColor: 'primary',
variant: 'pill'
}
}
}
})