Usage
Pass an array of arrays to the items
prop of the Dropdown component. Each array represents a group of items. Each item can have the following properties:
label
- The label of the item.labelClass
- The class of the item label.icon
- The icon of the item.iconClass
- The class of the item icon.avatar
- The avatar of the item. You can pass all the props of the Avatar component.shortcuts
- The shortcuts of the item.slot
- The slot of the item.disabled
- Whether the item is disabled.class
- The class of the item.click
- The click handler of the item.
You can also pass any property from the NuxtLink component such as to
, exact
, etc.
<script setup lang="ts">
const items = [
[{
label: 'Profile',
avatar: {
src: 'https://avatars.githubusercontent.com/u/739984?v=4'
}
}], [{
label: 'Edit',
icon: 'i-heroicons-pencil-square-20-solid',
shortcuts: ['E'],
click: () => {
console.log('Edit')
}
}, {
label: 'Duplicate',
icon: 'i-heroicons-document-duplicate-20-solid',
shortcuts: ['D'],
disabled: true
}], [{
label: 'Archive',
icon: 'i-heroicons-archive-box-20-solid'
}, {
label: 'Move',
icon: 'i-heroicons-arrow-right-circle-20-solid'
}], [{
label: 'Delete',
icon: 'i-heroicons-trash-20-solid',
shortcuts: ['⌘', 'D']
}]
]
</script>
<template>
<UDropdown :items="items" :popper="{ placement: 'bottom-start' }">
<UButton color="white" label="Options" trailing-icon="i-heroicons-chevron-down-20-solid" />
</UDropdown>
</template>
Mode
Use the mode
prop to switch between click
and hover
modes.
<script setup lang="ts">
const items = [
[{
label: 'Profile',
avatar: {
src: 'https://avatars.githubusercontent.com/u/739984?v=4'
}
}]
]
</script>
<template>
<UDropdown :items="items" mode="hover" :popper="{ placement: 'bottom-start' }">
<UButton color="white" label="Options" trailing-icon="i-heroicons-chevron-down-20-solid" />
</UDropdown>
</template>
Manual
Use a v-model:open
to manually control the state. In this example, press O to toggle the dropdown.
<script setup lang="ts">
const items = [
[{
label: 'Profile',
avatar: {
src: 'https://avatars.githubusercontent.com/u/739984?v=4'
}
}]
]
const open = ref(true)
defineShortcuts({
o: () => open.value = !open.value
})
</script>
<template>
<UDropdown v-model:open="open" :items="items" :popper="{ placement: 'bottom-start' }">
<UButton color="white" label="Options" trailing-icon="i-heroicons-chevron-down-20-solid" />
</UDropdown>
</template>
Popper
Use the popper
prop to customize the popper instance.
Arrow
<script setup lang="ts">
const items = [
[{
label: 'Profile',
avatar: {
src: 'https://avatars.githubusercontent.com/u/739984?v=4'
}
}]
]
</script>
<template>
<UDropdown :items="items" :popper="{ arrow: true }">
<UButton color="white" label="Options" trailing-icon="i-heroicons-chevron-down-20-solid" />
</UDropdown>
</template>
Placement
<script setup lang="ts">
const items = [
[{
label: 'Profile',
avatar: {
src: 'https://avatars.githubusercontent.com/u/739984?v=4'
}
}]
]
</script>
<template>
<UDropdown :items="items" :popper="{ placement: 'right-start' }">
<UButton color="white" label="Options" trailing-icon="i-heroicons-chevron-down-20-solid" />
</UDropdown>
</template>
Offset
<script setup lang="ts">
const items = [
[{
label: 'Profile',
avatar: {
src: 'https://avatars.githubusercontent.com/u/739984?v=4'
}
}]
]
</script>
<template>
<UDropdown :items="items" :popper="{ offsetDistance: 0, placement: 'right-start' }">
<UButton color="white" label="Options" trailing-icon="i-heroicons-chevron-down-20-solid" />
</UDropdown>
</template>
Slots
item
Use the #item
slot to customize the items content or pass a slot
property to customize a specific item. You will have access to the item
property in the slot scope.
<script setup lang="ts">
const items = [
[{
label: '[email protected]',
slot: 'account',
disabled: true
}], [{
label: 'Settings',
icon: 'i-heroicons-cog-8-tooth'
}], [{
label: 'Documentation',
icon: 'i-heroicons-book-open'
}, {
label: 'Changelog',
icon: 'i-heroicons-megaphone'
}, {
label: 'Status',
icon: 'i-heroicons-signal'
}], [{
label: 'Sign out',
icon: 'i-heroicons-arrow-left-on-rectangle'
}]
]
</script>
<template>
<UDropdown :items="items" :ui="{ item: { disabled: 'cursor-text select-text' } }" :popper="{ placement: 'bottom-start' }">
<UAvatar src="https://avatars.githubusercontent.com/u/739984?v=4" />
<template #account="{ item }">
<div class="text-left">
<p>
Signed in as
</p>
<p class="truncate font-medium text-gray-900 dark:text-white">
{{ item.label }}
</p>
</div>
</template>
<template #item="{ item }">
<span class="truncate">{{ item.label }}</span>
<UIcon :name="item.icon" class="flex-shrink-0 h-4 w-4 text-gray-400 dark:text-gray-500 ms-auto" />
</template>
</UDropdown>
</template>
Props
ui
{ wrapper?: string; container?: string; trigger?: string; width?: string; height?: string; background?: string; shadow?: string; rounded?: string; ring?: string; base?: string; divide?: string; padding?: string; ... 4 more ...; arrow?: DeepPartial<...>; } & { ...; } & { ...; }
{}
mode
"click" | "hover"
"click"
items
DropdownItem[][]
[]
popper
PopperOptions
{}
openDelay
number
config.default.openDelay
closeDelay
number
config.default.closeDelay
disabled
boolean
false
open
boolean
undefined
Config
{
wrapper: 'relative inline-flex text-left rtl:text-right',
container: 'z-20 group',
trigger: 'inline-flex w-full',
width: 'w-48',
height: '',
background: 'bg-white dark:bg-gray-800',
shadow: 'shadow-lg',
rounded: 'rounded-md',
ring: 'ring-1 ring-gray-200 dark:ring-gray-700',
base: 'relative focus:outline-none overflow-y-auto scroll-py-1',
divide: 'divide-y divide-gray-200 dark:divide-gray-700',
padding: 'p-1',
item: {
base: 'group flex items-center gap-1.5 w-full',
rounded: 'rounded-md',
padding: 'px-1.5 py-1.5',
size: 'text-sm',
active: 'bg-gray-100 dark:bg-gray-900 text-gray-900 dark:text-white',
inactive: 'text-gray-700 dark:text-gray-200',
disabled: 'cursor-not-allowed opacity-50',
icon: {
base: 'flex-shrink-0 w-5 h-5',
active: 'text-gray-500 dark:text-gray-400',
inactive: 'text-gray-400 dark:text-gray-500'
},
avatar: {
base: 'flex-shrink-0',
size: '2xs'
},
label: 'truncate',
shortcuts: 'hidden md:inline-flex flex-shrink-0 gap-0.5 ms-auto'
},
transition: {
enterActiveClass: 'transition duration-100 ease-out',
enterFromClass: 'transform scale-95 opacity-0',
enterToClass: 'transform scale-100 opacity-100',
leaveActiveClass: 'transition duration-75 ease-in',
leaveFromClass: 'transform scale-100 opacity-100',
leaveToClass: 'transform scale-95 opacity-0'
},
popper: {
placement: 'bottom-end',
strategy: 'fixed'
},
default: {
openDelay: 0,
closeDelay: 0
},
arrow: {
base: 'invisible before:visible before:block before:rotate-45 before:z-[-1] before:w-2 before:h-2',
ring: 'before:ring-1 before:ring-gray-200 dark:before:ring-gray-700',
rounded: 'before:rounded-sm',
background: 'before:bg-white dark:before:bg-gray-700',
shadow: 'before:shadow',
placement: "group-data-[popper-placement*='right']:-left-1 group-data-[popper-placement*='left']:-right-1 group-data-[popper-placement*='top']:-bottom-1 group-data-[popper-placement*='bottom']:-top-1"
}
}