Skip to content

Dropdown ​

A simple items-based dropdown with trigger modes, sizes, split buttons, submenus, icons, search, checkboxes, badges, groups, loading, and more.

Basic ​

vue
<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.

vue
<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.

vue
<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.

vue
<VxDropdown :items="[
  { label: 'Profile', icon: 'user', shortcut: '⇧⌘P' },
  { label: 'Settings', icon: 'settings', shortcut: '⌘,' },
]">
  <VxButton>My Account</VxButton>
</VxDropdown>

Sizes ​

vue
<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.

vue
<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.

vue
<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.

vue
<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.

vue
<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.

vue
<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.

vue
<VxDropdown :items="items" filterable>
  <VxButton>Fruits</VxButton>
</VxDropdown>

Split Button ​

vue
<VxDropdown :items="items" split-button @click="onMainClick">
  Actions
</VxDropdown>

Items with children show a nested submenu on hover.

vue
<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.

vue
<VxDropdown :items="[
  { label: 'Edit', icon: 'edit' },
  { label: 'Delete', icon: 'trash', destructive: true, divided: true },
]" />

Custom Colors ​

Set color on individual items for custom colors.

vue
<VxDropdown :items="[
  { label: 'Success', color: '#22c55e' },
  { label: 'Warning', color: '#f59e0b' },
  { label: 'Danger', color: '#ef4444' },
]" />

Popconfirm ​

Items with confirm show a confirmation inline before executing.

vue
<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.

vue
<VxDropdown :items="[
  { label: 'Edit', value: 'edit' },
  { label: 'Archive', disabled: true, disabledReason: 'You need admin permissions' },
]" />

Loading ​

Show skeleton placeholders while items load.

vue
<VxDropdown :items="items" loading>
  <VxButton>Loading...</VxButton>
</VxDropdown>

Max Height ​

vue
<VxDropdown :items="items" :max-height="200" />
vue
<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.

vue
<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 ​

vue
<VxDropdown :items="items" placement="bottom-start">...</VxDropdown>
<VxDropdown :items="items" placement="bottom">...</VxDropdown>
<VxDropdown :items="items" placement="bottom-end">...</VxDropdown>

Disabled ​

API ​

VxDropdown Props ​

PropTypeDefaultDescription
itemsDropdownItem[][]Menu items
v-modelboolean—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
disabledbooleanfalseDisable the dropdown
split-buttonbooleanfalseSplit button mode
hide-on-clickbooleantrueClose after selecting
max-heightnumber0Max panel height (scrollable)
show-arrowbooleanfalseShow pointer arrow
widthstring''Custom panel width
filterablebooleanfalseShow search input
filter-placeholderstring'Search...'Search placeholder
loadingbooleanfalseShow loading skeleton
teleportstring | booleanfalseTeleport panel to target
root-classstring | string[] | object—Class on root
PropertyTypeDefaultDescription
labelstring—Display text
valuestring | numberlabelValue emitted on command
iconstring—Built-in icon name
descriptionstring—Secondary text under label
shortcutstring—Keyboard shortcut hint
badgestring | number—Badge content
badgeType'default' | 'primary' | 'success' | 'warning' | 'danger''default'Badge color
type'default' | 'checkbox' | 'radio''default'Item type
checkedboolean—Checkbox/radio state
groupstring—Group label (items with same group are grouped)
disabledboolean—Disable this item
disabledReasonstring—Tooltip shown on disabled hover
destructiveboolean—Red destructive styling
colorstring—Custom color override
dividedboolean—Show divider above
confirmstring—Confirmation message before executing
action(item) => void—Callback fired when item is clicked
childrenDropdownItem[]—Nested submenu

Events ​

EventPayloadDescription
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 ​

SlotPropsDescription
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 ​

NameTypeDescription
show()() => voidOpen
hide()() => voidClose
toggle()() => voidToggle