Dropdown
A simple items-based dropdown with trigger modes, sizes, split buttons, submenus, icons, search, checkboxes, badges, groups, loading, and more.
Basic
<script setup>
import { VxDropdown } from 'veloxui'
const items = [
{ label: 'Edit', icon: 'edit', value: 'edit' },
{ label: 'Duplicate', icon: 'copy', value: 'duplicate' },
{ label: 'Share', icon: 'share', value: 'share' },
{ label: 'Delete', icon: 'trash', value: 'delete', divided: true, destructive: true },
]
</script>
<template>
<VxDropdown :items="items" @command="onCommand">
<VxButton>Actions</VxButton>
</VxDropdown>
</template>Item Actions
Add an action callback directly on each item — no need to handle @command separately.
<script setup>
import { ref } from 'vue'
const message = ref('')
const items = [
{
label: 'Copy',
icon: 'copy',
action: () => { message.value = 'Copied to clipboard!' },
},
{
label: 'Download',
icon: 'download',
action: (item) => {
console.log('Downloading:', item.label)
message.value = 'Download started...'
},
},
{
label: 'Share Link',
icon: 'link',
action: () => { message.value = 'Link shared!' },
},
{
label: 'Delete',
icon: 'trash',
destructive: true,
divided: true,
confirm: 'Are you sure?',
action: () => { message.value = 'Item deleted!' },
},
]
</script>
<template>
<VxDropdown :items="items">
<VxButton>Actions</VxButton>
</VxDropdown>
<span>{{ message }}</span>
</template>Trigger Modes
Supports click (default), hover, and contextmenu triggers.
<VxDropdown :items="items" trigger="click">...</VxDropdown>
<VxDropdown :items="items" trigger="hover">...</VxDropdown>
<VxDropdown :items="items" trigger="contextmenu">...</VxDropdown>Keyboard Shortcuts
Display shortcut hints next to items.
<VxDropdown :items="[
{ label: 'Profile', icon: 'user', shortcut: '⇧⌘P' },
{ label: 'Settings', icon: 'settings', shortcut: '⌘,' },
]">
<VxButton>My Account</VxButton>
</VxDropdown>Sizes
<VxDropdown :items="items" size="small">...</VxDropdown>
<VxDropdown :items="items" size="default">...</VxDropdown>
<VxDropdown :items="items" size="large">...</VxDropdown>Item Descriptions
Add a secondary description line to items.
<VxDropdown :items="[
{ label: 'Public', icon: 'link', description: 'Anyone with the link can view' },
{ label: 'Team', icon: 'user', description: 'Only team members can access' },
{ label: 'Private', icon: 'folder', description: 'Only you can see this' },
]" width="260px">
<VxButton>Visibility</VxButton>
</VxDropdown>Checkbox Items
Items with type: 'checkbox' show a toggleable check indicator.
<script setup>
import { reactive } from 'vue'
const items = reactive([
{ label: 'Show Toolbar', type: 'checkbox', checked: true },
{ label: 'Show Sidebar', type: 'checkbox', checked: false },
{ label: 'Word Wrap', type: 'checkbox', checked: false },
])
</script>
<template>
<VxDropdown :items="items" :hide-on-click="false" />
</template>Radio Items
Items with type: 'radio' and same group act as a radio group.
<script setup>
import { reactive } from 'vue'
const items = reactive([
{ label: 'Light', type: 'radio', group: 'theme', checked: true },
{ label: 'Dark', type: 'radio', group: 'theme', checked: false },
{ label: 'System', type: 'radio', group: 'theme', checked: false },
])
</script>
<template>
<VxDropdown :items="items" :hide-on-click="false" />
</template>Badges
Show badges next to items with different types: default, primary, success, warning, danger.
<VxDropdown :items="[
{ label: 'Inbox', icon: 'mail', badge: 12, badgeType: 'primary' },
{ label: 'Updates', icon: 'star', badge: 'New', badgeType: 'success' },
{ label: 'Alerts', icon: 'heart', badge: 3, badgeType: 'danger' },
]">
<VxButton>Notifications</VxButton>
</VxDropdown>Grouped Items
Group items with the group property.
<VxDropdown :items="[
{ label: 'Profile', icon: 'user', value: 'profile', group: 'Account' },
{ label: 'Settings', icon: 'settings', value: 'settings', group: 'Account' },
{ label: 'New File', icon: 'file', value: 'new', group: 'Actions' },
{ label: 'Upload', icon: 'upload', value: 'upload', group: 'Actions' },
{ label: 'Download', icon: 'download', value: 'download', group: 'Actions' },
{ label: 'Log out', icon: 'logout', value: 'logout', divided: true, destructive: true },
]" width="200px">
<VxButton>Menu</VxButton>
</VxDropdown>Search / Filter
Set filterable to add a search input that filters items in real-time.
<VxDropdown :items="items" filterable>
<VxButton>Fruits</VxButton>
</VxDropdown>Split Button
<VxDropdown :items="items" split-button @click="onMainClick">
Actions
</VxDropdown>Submenu
Items with children show a nested submenu on hover.
<VxDropdown :items="[
{ label: 'New File', icon: 'file' },
{ label: 'Share', icon: 'share', children: [
{ label: 'Copy Link' },
{ label: 'Email' },
] },
]">
<VxButton>File Actions</VxButton>
</VxDropdown>Destructive Items
Items with destructive: true are styled in red.
<VxDropdown :items="[
{ label: 'Edit', icon: 'edit' },
{ label: 'Delete', icon: 'trash', destructive: true, divided: true },
]" />Custom Colors
Set color on individual items for custom colors.
<VxDropdown :items="[
{ label: 'Success', color: '#22c55e' },
{ label: 'Warning', color: '#f59e0b' },
{ label: 'Danger', color: '#ef4444' },
]" />Popconfirm
Items with confirm show a confirmation inline before executing.
<VxDropdown :items="[
{ label: 'Save', icon: 'check' },
{ label: 'Delete All', icon: 'trash', destructive: true, confirm: 'Delete everything?' },
]" />Disabled Items with Tooltip
Disabled items can show a reason tooltip on hover.
<VxDropdown :items="[
{ label: 'Edit', value: 'edit' },
{ label: 'Archive', disabled: true, disabledReason: 'You need admin permissions' },
]" />Loading
Show skeleton placeholders while items load.
<VxDropdown :items="items" loading>
<VxButton>Loading...</VxButton>
</VxDropdown>Max Height
<VxDropdown :items="items" :max-height="200" />Header & Footer Slots
<VxDropdown :items="items">
<template #header><strong>Quick Actions</strong></template>
<template #footer>Press ⌘K for more</template>
</VxDropdown>Controlled (v-model)
Use v-model to control the open state programmatically.
<script setup>
const open = ref(false)
</script>
<template>
<VxButton @click="open = !open">Toggle</VxButton>
<VxDropdown v-model="open" :items="items">
<VxButton>Controlled</VxButton>
</VxDropdown>
</template>Placement
<VxDropdown :items="items" placement="bottom-start">...</VxDropdown>
<VxDropdown :items="items" placement="bottom">...</VxDropdown>
<VxDropdown :items="items" placement="bottom-end">...</VxDropdown>Disabled
API
VxDropdown Props
| Prop | Type | Default | Description |
|---|---|---|---|
items | DropdownItem[] | [] | Menu items |
v-model | boolean | — | Controlled open state |
trigger | 'click' | 'hover' | 'contextmenu' | 'click' | How to open |
placement | 'bottom-start' | 'bottom' | 'bottom-end' | 'top-start' | 'top' | 'top-end' | 'bottom-start' | Panel position |
size | 'small' | 'default' | 'large' | 'default' | Size variant |
disabled | boolean | false | Disable the dropdown |
split-button | boolean | false | Split button mode |
hide-on-click | boolean | true | Close after selecting |
max-height | number | 0 | Max panel height (scrollable) |
show-arrow | boolean | false | Show pointer arrow |
width | string | '' | Custom panel width |
filterable | boolean | false | Show search input |
filter-placeholder | string | 'Search...' | Search placeholder |
loading | boolean | false | Show loading skeleton |
teleport | string | boolean | false | Teleport panel to target |
root-class | string | string[] | object | — | Class on root |
DropdownItem
| Property | Type | Default | Description |
|---|---|---|---|
label | string | — | Display text |
value | string | number | label | Value emitted on command |
icon | string | — | Built-in icon name |
description | string | — | Secondary text under label |
shortcut | string | — | Keyboard shortcut hint |
badge | string | number | — | Badge content |
badgeType | 'default' | 'primary' | 'success' | 'warning' | 'danger' | 'default' | Badge color |
type | 'default' | 'checkbox' | 'radio' | 'default' | Item type |
checked | boolean | — | Checkbox/radio state |
group | string | — | Group label (items with same group are grouped) |
disabled | boolean | — | Disable this item |
disabledReason | string | — | Tooltip shown on disabled hover |
destructive | boolean | — | Red destructive styling |
color | string | — | Custom color override |
divided | boolean | — | Show divider above |
confirm | string | — | Confirmation message before executing |
action | (item) => void | — | Callback fired when item is clicked |
children | DropdownItem[] | — | Nested submenu |
Events
| Event | Payload | Description |
|---|---|---|
command | (value, item) | Item selected |
click | (event) | Main button clicked (split mode) |
visible-change | (visible) | Dropdown opened/closed |
update:modelValue | (boolean) | v-model sync |
check-change | (item, checked) | Checkbox/radio toggled |
Slots
| Slot | Props | Description |
|---|---|---|
default | — | Trigger content |
dropdown | — | Full custom dropdown content |
item | { item, index } | Custom item rendering |
icon | { item } | Custom icon per item |
header | — | Content above items |
footer | — | Content below items |
empty | — | Shown when no items match filter |
Exposed
| Name | Type | Description |
|---|---|---|
show() | () => void | Open |
hide() | () => void | Close |
toggle() | () => void | Toggle |