Dropdown
Простой dropdown на основе массива элементов с разными режимами триггера, размерами, split-кнопками, подменю, иконками, поиском, чекбоксами, бейджами, группами, состоянием загрузки и многим другим.
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
Добавьте callback action прямо на каждый элемент — отдельно обрабатывать @command не нужно.
<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
Поддерживаются триггеры click (по умолчанию), hover и contextmenu.
<VxDropdown :items="items" trigger="click">...</VxDropdown>
<VxDropdown :items="items" trigger="hover">...</VxDropdown>
<VxDropdown :items="items" trigger="contextmenu">...</VxDropdown>Keyboard Shortcuts
Отображает подсказки горячих клавиш рядом с элементами.
<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
Добавляйте к элементам вторую строку с описанием.
<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
Элементы с type: 'checkbox' показывают переключаемую отметку.
<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
Элементы с type: 'radio' и одинаковым group работают как radio-группа.
<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
Показывает бейджи рядом с элементами разных типов: 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.
<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
Установите filterable, чтобы добавить поле поиска, фильтрующее элементы в реальном времени.
<VxDropdown :items="items" filterable>
<VxButton>Fruits</VxButton>
</VxDropdown>Split Button
<VxDropdown :items="items" split-button @click="onMainClick">
Actions
</VxDropdown>Submenu
Элементы с children показывают вложенное подменю при наведении.
<VxDropdown :items="[
{ label: 'New File', icon: 'file' },
{ label: 'Share', icon: 'share', children: [
{ label: 'Copy Link' },
{ label: 'Email' },
] },
]">
<VxButton>File Actions</VxButton>
</VxDropdown>Destructive Items
Элементы с destructive: true оформлены красным.
<VxDropdown :items="[
{ label: 'Edit', icon: 'edit' },
{ label: 'Delete', icon: 'trash', destructive: true, divided: true },
]" />Custom Colors
Задавайте color у отдельных элементов для пользовательских цветов.
<VxDropdown :items="[
{ label: 'Success', color: '#22c55e' },
{ label: 'Warning', color: '#f59e0b' },
{ label: 'Danger', color: '#ef4444' },
]" />Popconfirm
Элементы с confirm показывают встроенное подтверждение перед выполнением.
<VxDropdown :items="[
{ label: 'Save', icon: 'check' },
{ label: 'Delete All', icon: 'trash', destructive: true, confirm: 'Delete everything?' },
]" />Disabled Items with Tooltip
Отключённые элементы могут показывать причину в tooltip при наведении.
<VxDropdown :items="[
{ label: 'Edit', value: 'edit' },
{ label: 'Archive', disabled: true, disabledReason: 'You need admin permissions' },
]" />Loading
Показывает skeleton-заглушки, пока элементы загружаются.
<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)
Используйте v-model для программного управления состоянием открытия.
<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[] | [] | Элементы меню |
v-model | boolean | — | Контролируемое состояние открытия |
trigger | 'click' | 'hover' | 'contextmenu' | 'click' | Способ открытия |
placement | 'bottom-start' | 'bottom' | 'bottom-end' | 'top-start' | 'top' | 'top-end' | 'bottom-start' | Позиция панели |
size | 'small' | 'default' | 'large' | 'default' | Вариант размера |
disabled | boolean | false | Отключить dropdown |
split-button | boolean | false | Режим split-кнопки |
hide-on-click | boolean | true | Закрывать после выбора |
max-height | number | 0 | Макс. высота панели (со скроллом) |
show-arrow | boolean | false | Показывать стрелку-указатель |
width | string | '' | Пользовательская ширина панели |
filterable | boolean | false | Показывать поле поиска |
filter-placeholder | string | 'Search...' | Подсказка для поиска |
loading | boolean | false | Показывать skeleton загрузки |
teleport | string | boolean | false | Telepor-ировать панель в цель |
root-class | string | string[] | object | — | Класс на корне |
DropdownItem
| Property | Type | Default | Description |
|---|---|---|---|
label | string | — | Отображаемый текст |
value | string | number | label | Значение, эмитится в command |
icon | string | — | Имя встроенной иконки |
description | string | — | Второстепенный текст под label |
shortcut | string | — | Подсказка горячей клавиши |
badge | string | number | — | Содержимое бейджа |
badgeType | 'default' | 'primary' | 'success' | 'warning' | 'danger' | 'default' | Цвет бейджа |
type | 'default' | 'checkbox' | 'radio' | 'default' | Тип элемента |
checked | boolean | — | Состояние checkbox/radio |
group | string | — | Имя группы (элементы с одинаковым group группируются) |
disabled | boolean | — | Отключить элемент |
disabledReason | string | — | Tooltip при наведении на disabled |
destructive | boolean | — | Красный destructive-стиль |
color | string | — | Переопределение цвета |
divided | boolean | — | Показать разделитель сверху |
confirm | string | — | Сообщение подтверждения перед выполнением |
action | (item) => void | — | Callback при клике по элементу |
children | DropdownItem[] | — | Вложенное подменю |
Events
| Event | Payload | Description |
|---|---|---|
command | (value, item) | Выбран элемент |
click | (event) | Нажата основная кнопка (в split-режиме) |
visible-change | (visible) | Dropdown открыт/закрыт |
update:modelValue | (boolean) | Синхронизация v-model |
check-change | (item, checked) | Переключён checkbox/radio |
Slots
| Slot | Props | Description |
|---|---|---|
default | — | Содержимое триггера |
dropdown | — | Полностью пользовательское содержимое dropdown |
item | { item, index } | Пользовательский рендер элемента |
icon | { item } | Пользовательская иконка для элемента |
header | — | Содержимое над элементами |
footer | — | Содержимое под элементами |
empty | — | Показывается, когда под фильтр ничего не подходит |
Exposed
| Name | Type | Description |
|---|---|---|
show() | () => void | Открыть |
hide() | () => void | Закрыть |
toggle() | () => void | Переключить |