Use a Button or any other component in the default slot of the DropdownMenu.
<script setup lang="ts">
import type { DropdownMenuItem } from '@nitro/ui'
const items = ref<DropdownMenuItem[][]>([
[
{
label: 'Benjamin',
avatar: {
src: 'https://github.com/benjamincanac.png',
loading: 'lazy'
},
type: 'label'
}
],
[
{
label: 'Profile',
icon: 'i-lucide-user'
},
{
label: 'Billing',
icon: 'i-lucide-credit-card'
},
{
label: 'Settings',
icon: 'i-lucide-cog',
kbds: [',']
},
{
label: 'Keyboard shortcuts',
icon: 'i-lucide-monitor'
}
],
[
{
label: 'Team',
icon: 'i-lucide-users',
filter: {
placeholder: 'Search members...'
},
children: [
[
{
label: 'benjamincanac',
avatar: {
src: 'https://github.com/benjamincanac.png',
loading: 'lazy'
}
},
{
label: 'HugoRCD',
avatar: {
src: 'https://github.com/HugoRCD.png',
loading: 'lazy'
}
},
{
label: 'romhml',
avatar: {
src: 'https://github.com/romhml.png',
loading: 'lazy'
}
},
{
label: 'sandros94',
avatar: {
src: 'https://github.com/sandros94.png',
loading: 'lazy'
}
},
{
label: 'hywax',
avatar: {
src: 'https://github.com/hywax.png',
loading: 'lazy'
}
},
{
label: 'J-Michalek',
avatar: {
src: 'https://github.com/J-Michalek.png',
loading: 'lazy'
}
},
{
label: 'genu',
avatar: {
src: 'https://github.com/genu.png',
loading: 'lazy'
}
}
]
]
},
{
label: 'Invite users',
icon: 'i-lucide-user-plus',
children: [
[
{
label: 'Email',
icon: 'i-lucide-mail'
},
{
label: 'Message',
icon: 'i-lucide-message-square'
}
],
[
{
label: 'More',
icon: 'i-lucide-circle-plus',
children: [
{
label: 'Import from Slack',
icon: 'i-simple-icons-slack',
to: 'https://slack.com',
target: '_blank'
},
{
label: 'Import from Trello',
icon: 'i-simple-icons-trello'
},
{
label: 'Import from Asana',
icon: 'i-simple-icons-asana'
}
]
}
]
]
},
{
label: 'New team',
icon: 'i-lucide-plus',
kbds: ['meta', 'n']
}
],
[
{
label: 'GitLab',
icon: 'i-simple-icons-gitlab',
to: 'https://github.com/nuxt/ui',
target: '_blank'
},
{
label: 'Support',
icon: 'i-lucide-life-buoy',
to: '/docs/components/dropdown-menu'
},
{
label: 'API',
icon: 'i-lucide-cloud',
disabled: true
}
],
[
{
label: 'Logout',
icon: 'i-lucide-log-out',
color: 'error',
kbds: ['shift', 'meta', 'q']
}
]
])
</script>
<template>
<NDropdownMenu :items="items">
<NButton icon="i-lucide-menu" color="neutral" variant="outline" />
</NDropdownMenu>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import type { DropdownMenuItem } from '@nitro/ui'
const items = ref<DropdownMenuItem[][]>([
[
{
label: 'Benjamin',
avatar: {
src: 'https://github.com/benjamincanac.png',
loading: 'lazy'
},
type: 'label'
}
],
[
{
label: 'Profile',
icon: 'i-lucide-user'
},
{
label: 'Billing',
icon: 'i-lucide-credit-card'
},
{
label: 'Settings',
icon: 'i-lucide-cog',
kbds: [',']
},
{
label: 'Keyboard shortcuts',
icon: 'i-lucide-monitor'
}
],
[
{
label: 'Team',
icon: 'i-lucide-users',
filter: {
placeholder: 'Search members...'
},
children: [
[
{
label: 'benjamincanac',
avatar: {
src: 'https://github.com/benjamincanac.png',
loading: 'lazy'
}
},
{
label: 'HugoRCD',
avatar: {
src: 'https://github.com/HugoRCD.png',
loading: 'lazy'
}
},
{
label: 'romhml',
avatar: {
src: 'https://github.com/romhml.png',
loading: 'lazy'
}
},
{
label: 'sandros94',
avatar: {
src: 'https://github.com/sandros94.png',
loading: 'lazy'
}
},
{
label: 'hywax',
avatar: {
src: 'https://github.com/hywax.png',
loading: 'lazy'
}
},
{
label: 'J-Michalek',
avatar: {
src: 'https://github.com/J-Michalek.png',
loading: 'lazy'
}
},
{
label: 'genu',
avatar: {
src: 'https://github.com/genu.png',
loading: 'lazy'
}
}
]
]
},
{
label: 'Invite users',
icon: 'i-lucide-user-plus',
children: [
[
{
label: 'Email',
icon: 'i-lucide-mail'
},
{
label: 'Message',
icon: 'i-lucide-message-square'
}
],
[
{
label: 'More',
icon: 'i-lucide-circle-plus',
children: [
{
label: 'Import from Slack',
icon: 'i-simple-icons-slack',
to: 'https://slack.com',
target: '_blank'
},
{
label: 'Import from Trello',
icon: 'i-simple-icons-trello'
},
{
label: 'Import from Asana',
icon: 'i-simple-icons-asana'
}
]
}
]
]
},
{
label: 'New team',
icon: 'i-lucide-plus',
kbds: ['meta', 'n']
}
],
[
{
label: 'GitLab',
icon: 'i-simple-icons-gitlab',
to: 'https://github.com/nuxt/ui',
target: '_blank'
},
{
label: 'Support',
icon: 'i-lucide-life-buoy',
to: '/docs/components/dropdown-menu'
},
{
label: 'API',
icon: 'i-lucide-cloud',
disabled: true
}
],
[
{
label: 'Logout',
icon: 'i-lucide-log-out',
color: 'error',
kbds: ['shift', 'meta', 'q']
}
]
])
</script>
<template>
<NDropdownMenu :items="items">
<NButton icon="i-lucide-menu" color="neutral" variant="outline" />
</NDropdownMenu>
</template>
Use a prop items como um array de objetos com as seguintes propriedades:
label?: stringicon?: stringavatar?: AvatarPropskbds?: string[] | KbdProps[]type?: "link" | "label" | "separator" | "checkbox"color?: "error" | "primary" | "secondary" | "success" | "info" | "warning" | "neutral"checked?: booleandisabled?: booleanslot?: stringonSelect?: (e: Event) => voidonUpdateChecked?: (checked: boolean) => voidchildren?: DropdownMenuItem[] | DropdownMenuItem[][]filter?: boolean | InputPropsfilterFields?: string[]ignoreFilter?: booleanclass?: anyui?: { item?: ClassNameValue, label?: ClassNameValue, separator?: ClassNameValue, itemLeadingIcon?: ClassNameValue, itemLeadingAvatarSize?: ClassNameValue, itemLeadingAvatar?: ClassNameValue, itemLabel?: ClassNameValue, itemLabelExternalIcon?: ClassNameValue, itemTrailing?: ClassNameValue, itemTrailingIcon?: ClassNameValue, itemTrailingKbds?: ClassNameValue, itemTrailingKbdsSize?: ClassNameValue }Você pode passar qualquer propriedade do componente Link, como to, target, etc.
<script setup lang="ts">
import type { DropdownMenuItem } from '@nitro/ui'
const items = ref<DropdownMenuItem[][]>([
[
{
label: 'Benjamin',
avatar: {
src: 'https://github.com/benjamincanac.png',
loading: 'lazy'
},
type: 'label'
}
],
[
{
label: 'Profile',
icon: 'i-lucide-user'
},
{
label: 'Billing',
icon: 'i-lucide-credit-card'
},
{
label: 'Settings',
icon: 'i-lucide-cog',
kbds: [',']
},
{
label: 'Keyboard shortcuts',
icon: 'i-lucide-monitor'
}
],
[
{
label: 'Team',
icon: 'i-lucide-users'
},
{
label: 'Invite users',
icon: 'i-lucide-user-plus',
children: [
[
{
label: 'Email',
icon: 'i-lucide-mail'
},
{
label: 'Message',
icon: 'i-lucide-message-square'
}
],
[
{
label: 'More',
icon: 'i-lucide-circle-plus',
children: [
{
label: 'Import from Slack',
icon: 'i-simple-icons-slack',
to: 'https://slack.com',
target: '_blank'
},
{
label: 'Import from Trello',
icon: 'i-simple-icons-trello'
},
{
label: 'Import from Asana',
icon: 'i-simple-icons-asana'
}
]
}
]
]
},
{
label: 'New team',
icon: 'i-lucide-plus',
kbds: ['meta', 'n']
}
],
[
{
label: 'GitLab',
icon: 'i-simple-icons-gitlab',
to: 'https://github.com/nuxt/ui',
target: '_blank'
},
{
label: 'Support',
icon: 'i-lucide-life-buoy',
to: '/docs/components/dropdown-menu'
},
{
label: 'API',
icon: 'i-lucide-cloud',
disabled: true
}
],
[
{
label: 'Logout',
icon: 'i-lucide-log-out',
kbds: ['shift', 'meta', 'q']
}
]
])
</script>
<template>
<NDropdownMenu
:items="items"
:ui="{
content: 'w-48'
}"
>
<NButton icon="i-lucide-menu" color="neutral" variant="outline" />
</NDropdownMenu>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import type { DropdownMenuItem } from '@nitro/ui'
const items = ref<DropdownMenuItem[][]>([
[
{
label: 'Benjamin',
avatar: {
src: 'https://github.com/benjamincanac.png',
loading: 'lazy'
},
type: 'label'
}
],
[
{
label: 'Profile',
icon: 'i-lucide-user'
},
{
label: 'Billing',
icon: 'i-lucide-credit-card'
},
{
label: 'Settings',
icon: 'i-lucide-cog',
kbds: [',']
},
{
label: 'Keyboard shortcuts',
icon: 'i-lucide-monitor'
}
],
[
{
label: 'Team',
icon: 'i-lucide-users'
},
{
label: 'Invite users',
icon: 'i-lucide-user-plus',
children: [
[
{
label: 'Email',
icon: 'i-lucide-mail'
},
{
label: 'Message',
icon: 'i-lucide-message-square'
}
],
[
{
label: 'More',
icon: 'i-lucide-circle-plus',
children: [
{
label: 'Import from Slack',
icon: 'i-simple-icons-slack',
to: 'https://slack.com',
target: '_blank'
},
{
label: 'Import from Trello',
icon: 'i-simple-icons-trello'
},
{
label: 'Import from Asana',
icon: 'i-simple-icons-asana'
}
]
}
]
]
},
{
label: 'New team',
icon: 'i-lucide-plus',
kbds: ['meta', 'n']
}
],
[
{
label: 'GitLab',
icon: 'i-simple-icons-gitlab',
to: 'https://github.com/nuxt/ui',
target: '_blank'
},
{
label: 'Support',
icon: 'i-lucide-life-buoy',
to: '/docs/components/dropdown-menu'
},
{
label: 'API',
icon: 'i-lucide-cloud',
disabled: true
}
],
[
{
label: 'Logout',
icon: 'i-lucide-log-out',
kbds: ['shift', 'meta', 'q']
}
]
])
</script>
<template>
<NDropdownMenu
:items="items"
:ui="{
content: 'w-48'
}"
>
<NButton icon="i-lucide-menu" color="neutral" variant="outline" />
</NDropdownMenu>
</template>
items para criar grupos separados de itens.children de objetos com as mesmas propriedades da prop items para criar um menu aninhado que pode ser controlado usando as propriedades open, defaultOpen e content.Use a prop content para controlar como o conteúdo do DropdownMenu é renderizado, como seu align ou side, por exemplo.
<script setup lang="ts">
import type { DropdownMenuItem } from '@nitro/ui'
const items = ref<DropdownMenuItem[]>([
{
label: 'Profile',
icon: 'i-lucide-user'
},
{
label: 'Billing',
icon: 'i-lucide-credit-card'
},
{
label: 'Settings',
icon: 'i-lucide-cog'
}
])
</script>
<template>
<NDropdownMenu
:items="items"
:content="{
align: 'start',
side: 'bottom',
sideOffset: 8
}"
:ui="{
content: 'w-48'
}"
>
<NButton label="Open" icon="i-lucide-menu" color="neutral" variant="outline" />
</NDropdownMenu>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import type { DropdownMenuItem } from '@nitro/ui'
const items = ref<DropdownMenuItem[]>([
{
label: 'Profile',
icon: 'i-lucide-user'
},
{
label: 'Billing',
icon: 'i-lucide-credit-card'
},
{
label: 'Settings',
icon: 'i-lucide-cog'
}
])
</script>
<template>
<NDropdownMenu
:items="items"
:content="{
align: 'start',
side: 'bottom',
sideOffset: 8
}"
:ui="{
content: 'w-48'
}"
>
<NButton label="Open" icon="i-lucide-menu" color="neutral" variant="outline" />
</NDropdownMenu>
</template>
Use a prop filter para exibir um campo de filtro dentro do DropdownMenu. O padrão é false.
filter-fields para especificar por quais campos filtrar. Por padrão, ela usa a prop labelKey.Você pode passar qualquer propriedade do componente Input para personalizá-lo.
<script setup lang="ts">
import type { DropdownMenuItem } from '@nitro/ui'
const items = ref<DropdownMenuItem[]>([
{
label: 'Profile',
icon: 'i-lucide-user'
},
{
label: 'Billing',
icon: 'i-lucide-credit-card'
},
{
label: 'Settings',
icon: 'i-lucide-cog'
},
{
label: 'Team',
icon: 'i-lucide-users'
},
{
label: 'Invite users',
icon: 'i-lucide-user-plus'
},
{
label: 'New team',
icon: 'i-lucide-plus'
}
])
</script>
<template>
<NDropdownMenu
:filter="{
icon: 'i-lucide-search'
}"
:items="items"
:content="{
align: 'start'
}"
:ui="{
content: 'w-48'
}"
>
<NButton label="Open" icon="i-lucide-menu" color="neutral" variant="outline" />
</NDropdownMenu>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import type { DropdownMenuItem } from '@nitro/ui'
const items = ref<DropdownMenuItem[]>([
{
label: 'Profile',
icon: 'i-lucide-user'
},
{
label: 'Billing',
icon: 'i-lucide-credit-card'
},
{
label: 'Settings',
icon: 'i-lucide-cog'
},
{
label: 'Team',
icon: 'i-lucide-users'
},
{
label: 'Invite users',
icon: 'i-lucide-user-plus'
},
{
label: 'New team',
icon: 'i-lucide-plus'
}
])
</script>
<template>
<NDropdownMenu
:filter="{
icon: 'i-lucide-search'
}"
:items="items"
:content="{
align: 'start'
}"
:ui="{
content: 'w-48'
}"
>
<NButton label="Open" icon="i-lucide-menu" color="neutral" variant="outline" />
</NDropdownMenu>
</template>
filter em itens com children.Use a prop arrow para exibir uma seta no DropdownMenu.
<script setup lang="ts">
import type { DropdownMenuItem } from '@nitro/ui'
const items = ref<DropdownMenuItem[]>([
{
label: 'Profile',
icon: 'i-lucide-user'
},
{
label: 'Billing',
icon: 'i-lucide-credit-card'
},
{
label: 'Settings',
icon: 'i-lucide-cog'
}
])
</script>
<template>
<NDropdownMenu
arrow
:items="items"
:ui="{
content: 'w-48'
}"
>
<NButton label="Open" icon="i-lucide-menu" color="neutral" variant="outline" />
</NDropdownMenu>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import type { DropdownMenuItem } from '@nitro/ui'
const items = ref<DropdownMenuItem[]>([
{
label: 'Profile',
icon: 'i-lucide-user'
},
{
label: 'Billing',
icon: 'i-lucide-credit-card'
},
{
label: 'Settings',
icon: 'i-lucide-cog'
}
])
</script>
<template>
<NDropdownMenu
arrow
:items="items"
:ui="{
content: 'w-48'
}"
>
<NButton label="Open" icon="i-lucide-menu" color="neutral" variant="outline" />
</NDropdownMenu>
</template>
Use a prop size para controlar o tamanho do DropdownMenu.
<script setup lang="ts">
import type { DropdownMenuItem } from '@nitro/ui'
const items = ref<DropdownMenuItem[]>([
{
label: 'Profile',
icon: 'i-lucide-user'
},
{
label: 'Billing',
icon: 'i-lucide-credit-card'
},
{
label: 'Settings',
icon: 'i-lucide-cog'
}
])
</script>
<template>
<NDropdownMenu
size="xl"
:items="items"
:content="{
align: 'start'
}"
:ui="{
content: 'w-48'
}"
>
<NButton size="xl" label="Open" icon="i-lucide-menu" color="neutral" variant="outline" />
</NDropdownMenu>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import type { DropdownMenuItem } from '@nitro/ui'
const items = ref<DropdownMenuItem[]>([
{
label: 'Profile',
icon: 'i-lucide-user'
},
{
label: 'Billing',
icon: 'i-lucide-credit-card'
},
{
label: 'Settings',
icon: 'i-lucide-cog'
}
])
</script>
<template>
<NDropdownMenu
size="xl"
:items="items"
:content="{
align: 'start'
}"
:ui="{
content: 'w-48'
}"
>
<NButton size="xl" label="Open" icon="i-lucide-menu" color="neutral" variant="outline" />
</NDropdownMenu>
</template>
size não é repassada ao Button; você precisa defini-la você mesmo.Use a prop modal para controlar se o DropdownMenu bloqueia a interação com o conteúdo externo. O padrão é true.
<script setup lang="ts">
import type { DropdownMenuItem } from '@nitro/ui'
const items = ref<DropdownMenuItem[]>([
{
label: 'Profile',
icon: 'i-lucide-user'
},
{
label: 'Billing',
icon: 'i-lucide-credit-card'
},
{
label: 'Settings',
icon: 'i-lucide-cog'
}
])
</script>
<template>
<NDropdownMenu
:modal="false"
:items="items"
:ui="{
content: 'w-48'
}"
>
<NButton label="Open" icon="i-lucide-menu" color="neutral" variant="outline" />
</NDropdownMenu>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import type { DropdownMenuItem } from '@nitro/ui'
const items = ref<DropdownMenuItem[]>([
{
label: 'Profile',
icon: 'i-lucide-user'
},
{
label: 'Billing',
icon: 'i-lucide-credit-card'
},
{
label: 'Settings',
icon: 'i-lucide-cog'
}
])
</script>
<template>
<NDropdownMenu
:modal="false"
:items="items"
:ui="{
content: 'w-48'
}"
>
<NButton label="Open" icon="i-lucide-menu" color="neutral" variant="outline" />
</NDropdownMenu>
</template>
Use a prop disabled para desabilitar o DropdownMenu.
<script setup lang="ts">
import type { DropdownMenuItem } from '@nitro/ui'
const items = ref<DropdownMenuItem[]>([
{
label: 'Profile',
icon: 'i-lucide-user'
},
{
label: 'Billing',
icon: 'i-lucide-credit-card'
},
{
label: 'Settings',
icon: 'i-lucide-cog'
}
])
</script>
<template>
<NDropdownMenu
disabled
:items="items"
:ui="{
content: 'w-48'
}"
>
<NButton label="Open" icon="i-lucide-menu" color="neutral" variant="outline" />
</NDropdownMenu>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import type { DropdownMenuItem } from '@nitro/ui'
const items = ref<DropdownMenuItem[]>([
{
label: 'Profile',
icon: 'i-lucide-user'
},
{
label: 'Billing',
icon: 'i-lucide-credit-card'
},
{
label: 'Settings',
icon: 'i-lucide-cog'
}
])
</script>
<template>
<NDropdownMenu
disabled
:items="items"
:ui="{
content: 'w-48'
}"
>
<NButton label="Open" icon="i-lucide-menu" color="neutral" variant="outline" />
</NDropdownMenu>
</template>
Você pode usar a propriedade type com checkbox e usar as propriedades checked / onUpdateChecked para controlar o estado marcado do item.
checked dos itens, é recomendado envolver seu array items dentro de um computed.Você pode usar a propriedade color para destacar certos itens com uma cor.
Você pode usar a propriedade filter em itens com children para exibir um campo de filtro dentro do submenu.
Você pode controlar o estado de abertura usando a prop default-open ou a diretiva v-model:open.
defineShortcuts, você pode abrir e fechar o DropdownMenu pressionando O.Use a propriedade slot para personalizar um item específico.
Você terá acesso aos seguintes slots:
#{{ item.slot }}#{{ item.slot }}-leading#{{ item.slot }}-label#{{ item.slot }}-trailing#item, #item-leading, #item-label e #item-trailing para personalizar todos os itens.Você pode usar a propriedade slot com um slot #{{ slot }}-trailing para renderizar um Switch dentro de um item.
Ao usar a prop filter ou o campo filter em itens com children, você pode definir a prop ignore-filter como true para desabilitar a busca interna e usar sua própria lógica de busca.
refDebounced para aplicar debounce nas chamadas de API. A busca é adiada com immediate: false, então nenhuma requisição é feita até o menu abrir.Ao usar a prop filter ou o campo filter em itens com children, você pode definir a prop filter-fields com um array de campos para filtrar. O padrão é [labelKey].
Você pode expandir o conteúdo até a largura total do seu botão adicionando a classe w-(--reka-dropdown-menu-trigger-width) no slot ui.content.
app.config.ts:export default defineAppConfig({
ui: {
dropdownMenu: {
slots: {
content: 'w-(--reka-dropdown-menu-trigger-width)'
}
}
}
})
Use o utilitário extractShortcuts para definir automaticamente atalhos a partir de itens de menu com uma propriedade kbds. Ele extrai os atalhos recursivamente e retorna um objeto compatível com defineShortcuts.
<script setup lang="ts">
import type { DropdownMenuItem } from '@nitro/ui'
const items: DropdownMenuItem[] = [{
label: 'Invite users',
icon: 'i-lucide-user-plus',
children: [{
label: 'Invite by email',
icon: 'i-lucide-send-horizontal',
kbds: ['meta', 'e'],
onSelect() {
console.log('Invite by email clicked')
}
}, {
label: 'Invite by link',
icon: 'i-lucide-link',
kbds: ['meta', 'i'],
onSelect() {
console.log('Invite by link clicked')
}
}]
}, {
label: 'New team',
icon: 'i-lucide-plus',
kbds: ['meta', 'n'],
onSelect() {
console.log('New team clicked')
}
}]
defineShortcuts(extractShortcuts(items))
</script>
select do item correspondente.| Prop | Default | Type |
|---|---|---|
size | 'md' | "sm" | "md" | "xs" | "lg" | "xl" |
items | T | |
checkedIcon | appConfig.ui.icons.check | anyThe icon displayed when an item is checked. |
loadingIcon | appConfig.ui.icons.loading | anyThe icon displayed when an item is loading. |
externalIcon | true | anyThe icon displayed when the item is an external link.
Set to |
content | { side: 'bottom', sideOffset: 8, collisionPadding: 8 } | DropdownMenuContentProps & Partial<EmitsToProps<MenuContentEmits>>The content of the menu. |
arrow | false | boolean | DropdownMenuArrowProps Display an arrow alongside the menu.
|
portal | true | string | false | true | HTMLElementRender the menu in a portal. |
labelKey | 'label' | keyof Extract<NestedItem<T>, object> & string | DotPathKeys<Extract<NestedItem<T>, object>>The key used to get the label from the item. |
descriptionKey | 'description' | keyof Extract<NestedItem<T>, object> & string | DotPathKeys<Extract<NestedItem<T>, object>>The key used to get the description from the item. |
filter | false | boolean | Omit<InputProps<AcceptableValue, ModelModifiers>, "modelValue" | "defaultValue"> Whether to display a filter input or not.
Can be an object to pass additional props to the input.
|
filterFields | [labelKey] | string[]The fields to filter by. |
ignoreFilter | false | boolean When |
disabled | boolean | |
defaultOpen | boolean The open state of the dropdown menu when it is initially rendered. Use when you do not need to control its open state. | |
open | boolean The controlled open state of the menu. Can be used as | |
modal | true | boolean The modality of the dropdown menu. When set to |
searchTerm | '' | string |
ui | { content?: SlotClass; input?: SlotClass; empty?: SlotClass; viewport?: SlotClass; arrow?: SlotClass; group?: SlotClass; label?: SlotClass; separator?: SlotClass; item?: SlotClass; itemLeadingIcon?: SlotClass; itemLeadingAvatar?: SlotClass; itemLeadingAvatarSize?: SlotClass; itemTrailing?: SlotClass; itemTrailingIcon?: SlotClass; itemTrailingKbds?: SlotClass; itemTrailingKbdsSize?: SlotClass; itemWrapper?: SlotClass; itemLabel?: SlotClass; itemDescription?: SlotClass; itemLabelExternalIcon?: SlotClass; } |
| Slot | Type |
|---|---|
default | { open: boolean; } |
item | { item: NestedItem<T>; active: boolean; index: number; ui: object; } |
item-leading | { item: NestedItem<T>; active: boolean; index: number; ui: object; } |
item-label | { item: NestedItem<T>; active: boolean; index: number; } |
item-description | { item: NestedItem<T>; active: boolean; index: number; } |
item-trailing | { item: NestedItem<T>; active: boolean; index: number; ui: object; } |
empty | { searchTerm: string; } |
content-top | { sub: boolean; } |
content-bottom | { sub: boolean; } |
| Event | Type |
|---|---|
update:open | [payload: boolean] |
update:searchTerm | [value: string] |
export default defineAppConfig({
ui: {
dropdownMenu: {
slots: {
content: 'min-w-32 bg-default shadow-lg rounded-md ring ring-default overflow-hidden data-[state=open]:animate-[scale-in_100ms_ease-out] data-[state=closed]:animate-[scale-out_100ms_ease-in] origin-(--reka-dropdown-menu-content-transform-origin) flex flex-col',
input: 'border-b border-default',
empty: 'text-center text-muted',
viewport: 'relative divide-y divide-default scroll-py-1 overflow-y-auto flex-1',
arrow: 'fill-bg stroke-default',
group: 'p-1 isolate',
label: 'w-full flex items-center font-semibold text-highlighted',
separator: '-mx-1 my-1 h-px bg-border',
item: 'group relative w-full flex items-start select-none outline-none before:absolute before:z-[-1] before:inset-px before:rounded-md data-disabled:cursor-not-allowed data-disabled:opacity-75',
itemLeadingIcon: 'shrink-0',
itemLeadingAvatar: 'shrink-0',
itemLeadingAvatarSize: '',
itemTrailing: 'ms-auto inline-flex gap-1.5 items-center',
itemTrailingIcon: 'shrink-0',
itemTrailingKbds: 'hidden lg:inline-flex items-center shrink-0',
itemTrailingKbdsSize: '',
itemWrapper: 'flex-1 flex flex-col text-start min-w-0',
itemLabel: 'truncate',
itemDescription: 'truncate text-muted',
itemLabelExternalIcon: 'inline-block size-3 align-top text-dimmed'
},
variants: {
color: {
primary: '',
secondary: '',
accent: '',
success: '',
info: '',
warning: '',
error: '',
neutral: ''
},
active: {
true: {
item: 'text-highlighted before:bg-elevated',
itemLeadingIcon: 'text-default'
},
false: {
item: [
'text-default data-highlighted:text-highlighted data-[state=open]:text-highlighted data-highlighted:before:bg-elevated/50 data-[state=open]:before:bg-elevated/50',
'transition-colors before:transition-colors'
],
itemLeadingIcon: [
'text-dimmed group-data-highlighted:text-default group-data-[state=open]:text-default',
'transition-colors'
]
}
},
loading: {
true: {
itemLeadingIcon: 'animate-spin'
}
},
size: {
xs: {
label: 'p-1 text-xs gap-1',
item: 'p-1 text-xs gap-1',
empty: 'p-2 text-xs',
itemLeadingIcon: 'size-4',
itemLeadingAvatarSize: '3xs',
itemTrailingIcon: 'size-4',
itemTrailingKbds: 'gap-0.5',
itemTrailingKbdsSize: 'sm'
},
sm: {
label: 'p-1.5 text-xs gap-1.5',
item: 'p-1.5 text-xs gap-1.5',
empty: 'p-2.5 text-xs',
itemLeadingIcon: 'size-4',
itemLeadingAvatarSize: '3xs',
itemTrailingIcon: 'size-4',
itemTrailingKbds: 'gap-0.5',
itemTrailingKbdsSize: 'sm'
},
md: {
label: 'p-1.5 text-sm gap-1.5',
item: 'p-1.5 text-sm gap-1.5',
empty: 'p-2.5 text-sm',
itemLeadingIcon: 'size-5',
itemLeadingAvatarSize: '2xs',
itemTrailingIcon: 'size-5',
itemTrailingKbds: 'gap-0.5',
itemTrailingKbdsSize: 'md'
},
lg: {
label: 'p-2 text-sm gap-2',
item: 'p-2 text-sm gap-2',
empty: 'p-3 text-sm',
itemLeadingIcon: 'size-5',
itemLeadingAvatarSize: '2xs',
itemTrailingIcon: 'size-5',
itemTrailingKbds: 'gap-1',
itemTrailingKbdsSize: 'md'
},
xl: {
label: 'p-2 text-base gap-2',
item: 'p-2 text-base gap-2',
empty: 'p-3 text-base',
itemLeadingIcon: 'size-6',
itemLeadingAvatarSize: 'xs',
itemTrailingIcon: 'size-6',
itemTrailingKbds: 'gap-1',
itemTrailingKbdsSize: 'lg'
}
}
},
compoundVariants: [
{
color: 'primary',
active: false,
class: {
item: 'text-primary data-highlighted:text-primary data-highlighted:before:bg-primary/10 data-[state=open]:before:bg-primary/10',
itemLeadingIcon: 'text-primary/75 group-data-highlighted:text-primary group-data-[state=open]:text-primary'
}
},
{
color: 'primary',
active: true,
class: {
item: 'text-primary before:bg-primary/10',
itemLeadingIcon: 'text-primary'
}
}
],
defaultVariants: {
size: 'md'
}
}
}
})
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import ui from '@nitro/ui/vite'
export default defineConfig({
plugins: [
vue(),
ui({
ui: {
dropdownMenu: {
slots: {
content: 'min-w-32 bg-default shadow-lg rounded-md ring ring-default overflow-hidden data-[state=open]:animate-[scale-in_100ms_ease-out] data-[state=closed]:animate-[scale-out_100ms_ease-in] origin-(--reka-dropdown-menu-content-transform-origin) flex flex-col',
input: 'border-b border-default',
empty: 'text-center text-muted',
viewport: 'relative divide-y divide-default scroll-py-1 overflow-y-auto flex-1',
arrow: 'fill-bg stroke-default',
group: 'p-1 isolate',
label: 'w-full flex items-center font-semibold text-highlighted',
separator: '-mx-1 my-1 h-px bg-border',
item: 'group relative w-full flex items-start select-none outline-none before:absolute before:z-[-1] before:inset-px before:rounded-md data-disabled:cursor-not-allowed data-disabled:opacity-75',
itemLeadingIcon: 'shrink-0',
itemLeadingAvatar: 'shrink-0',
itemLeadingAvatarSize: '',
itemTrailing: 'ms-auto inline-flex gap-1.5 items-center',
itemTrailingIcon: 'shrink-0',
itemTrailingKbds: 'hidden lg:inline-flex items-center shrink-0',
itemTrailingKbdsSize: '',
itemWrapper: 'flex-1 flex flex-col text-start min-w-0',
itemLabel: 'truncate',
itemDescription: 'truncate text-muted',
itemLabelExternalIcon: 'inline-block size-3 align-top text-dimmed'
},
variants: {
color: {
primary: '',
secondary: '',
accent: '',
success: '',
info: '',
warning: '',
error: '',
neutral: ''
},
active: {
true: {
item: 'text-highlighted before:bg-elevated',
itemLeadingIcon: 'text-default'
},
false: {
item: [
'text-default data-highlighted:text-highlighted data-[state=open]:text-highlighted data-highlighted:before:bg-elevated/50 data-[state=open]:before:bg-elevated/50',
'transition-colors before:transition-colors'
],
itemLeadingIcon: [
'text-dimmed group-data-highlighted:text-default group-data-[state=open]:text-default',
'transition-colors'
]
}
},
loading: {
true: {
itemLeadingIcon: 'animate-spin'
}
},
size: {
xs: {
label: 'p-1 text-xs gap-1',
item: 'p-1 text-xs gap-1',
empty: 'p-2 text-xs',
itemLeadingIcon: 'size-4',
itemLeadingAvatarSize: '3xs',
itemTrailingIcon: 'size-4',
itemTrailingKbds: 'gap-0.5',
itemTrailingKbdsSize: 'sm'
},
sm: {
label: 'p-1.5 text-xs gap-1.5',
item: 'p-1.5 text-xs gap-1.5',
empty: 'p-2.5 text-xs',
itemLeadingIcon: 'size-4',
itemLeadingAvatarSize: '3xs',
itemTrailingIcon: 'size-4',
itemTrailingKbds: 'gap-0.5',
itemTrailingKbdsSize: 'sm'
},
md: {
label: 'p-1.5 text-sm gap-1.5',
item: 'p-1.5 text-sm gap-1.5',
empty: 'p-2.5 text-sm',
itemLeadingIcon: 'size-5',
itemLeadingAvatarSize: '2xs',
itemTrailingIcon: 'size-5',
itemTrailingKbds: 'gap-0.5',
itemTrailingKbdsSize: 'md'
},
lg: {
label: 'p-2 text-sm gap-2',
item: 'p-2 text-sm gap-2',
empty: 'p-3 text-sm',
itemLeadingIcon: 'size-5',
itemLeadingAvatarSize: '2xs',
itemTrailingIcon: 'size-5',
itemTrailingKbds: 'gap-1',
itemTrailingKbdsSize: 'md'
},
xl: {
label: 'p-2 text-base gap-2',
item: 'p-2 text-base gap-2',
empty: 'p-3 text-base',
itemLeadingIcon: 'size-6',
itemLeadingAvatarSize: 'xs',
itemTrailingIcon: 'size-6',
itemTrailingKbds: 'gap-1',
itemTrailingKbdsSize: 'lg'
}
}
},
compoundVariants: [
{
color: 'primary',
active: false,
class: {
item: 'text-primary data-highlighted:text-primary data-highlighted:before:bg-primary/10 data-[state=open]:before:bg-primary/10',
itemLeadingIcon: 'text-primary/75 group-data-highlighted:text-primary group-data-[state=open]:text-primary'
}
},
{
color: 'primary',
active: true,
class: {
item: 'text-primary before:bg-primary/10',
itemLeadingIcon: 'text-primary'
}
}
],
defaultVariants: {
size: 'md'
}
}
}
})
]
})