DropdownMenu ​
Usage ​
Use a Button or any other component in the default slot of the DropdownMenu.
Items ​
Use the items
prop as an array of objects with the following properties:
label?: string
icon?: FunctionalComponent<HTMLAttributes & VNodeProps>
color?: string
avatar?: AvatarProps
kbds?: string[] | KbdProps[]
type?: "link" | "label" | "separator" | "checkbox"
color?: "error" | "primary" | "secondary" | "success" | "info" | "warning" | "neutral"
checked?: boolean
disabled?: boolean
class?: any
slot?: string
onSelect?(e: Event): void
onUpdateChecked?(checked: boolean): void
You can pass any property from the Link component such as to
, target
, etc.
Details
<script setup lang="ts">
import { ref } from 'vue'
import PersonIcon from '@bitrix24/b24icons-vue/main/PersonIcon'
import CreditDebitCardIcon from '@bitrix24/b24icons-vue/main/CreditDebitCardIcon'
import Settings2Icon from '@bitrix24/b24icons-vue/actions/Settings2Icon'
import Persons3Icon from '@bitrix24/b24icons-vue/main/Persons3Icon'
import PersonPlus2Icon from '@bitrix24/b24icons-vue/crm/PersonPlus2Icon'
import SendIcon from '@bitrix24/b24icons-vue/main/SendIcon'
import Link3Icon from '@bitrix24/b24icons-vue/main/Link3Icon'
import CirclePlusIcon from '@bitrix24/b24icons-vue/main/CirclePlusIcon'
import SlackIcon from '@bitrix24/b24icons-vue/social/SlackIcon'
import PlusInCircleIcon from '@bitrix24/b24icons-vue/actions/PlusInCircleIcon'
import PulseCircleIcon from '@bitrix24/b24icons-vue/main/PulseCircleIcon'
import ItemIcon from '@bitrix24/b24icons-vue/crm/ItemIcon'
import CrossCircle50Icon from '@bitrix24/b24icons-vue/actions/CrossCircle50Icon'
import CircleCheckThinIcon from '@bitrix24/b24icons-vue/main/CircleCheckThinIcon'
import MenuIcon from '@bitrix24/b24icons-vue/main/MenuIcon'
import Bitrix24Icon from '@bitrix24/b24icons-vue/common-service/Bitrix24Icon'
import LoaderWaitIcon from '@bitrix24/b24icons-vue/animated/LoaderWaitIcon'
const toast = useToast()
const loading = ref(false)
const items = ref([
[
{
label: 'My account',
avatar: {
src: '/b24ui/avatar/employee.png'
},
type: 'label' as const
}
],
[
{
label: 'Profile',
icon: PersonIcon,
slot: 'custom' as const,
onSelect(e: Event) {
e.preventDefault()
toast.add({ title: 'Action', description: 'Profile clicked' })
}
},
{
label: 'Billing',
icon: CreditDebitCardIcon,
kbds: ['meta', 'b'],
onSelect() {
toast.add({ title: 'Action', description: 'Billing clicked' })
}
},
{
label: 'Settings',
icon: Settings2Icon,
kbds: ['?'],
onSelect() {
toast.add({ title: 'Action', description: 'Settings clicked' })
}
}
],
[
{
label: 'Team',
icon: Persons3Icon
},
{
label: 'Invite users',
icon: PersonPlus2Icon,
children: [
[
{
label: 'Invite by email',
icon: SendIcon
},
{
label: 'Invite by link',
icon: Link3Icon,
kbds: ['meta', 'i'],
onSelect(e: Event) {
e?.preventDefault()
toast.add({ title: 'Action', description: 'Invite by link clicked' })
}
}
],
[
{
label: 'More',
icon: PlusInCircleIcon,
children: [
{
label: 'Import from Bitrix24',
icon: Bitrix24Icon,
to: 'https://bitrix24.com',
target: '_blank',
onSelect(e: Event) {
e.preventDefault()
toast.add({ title: 'Action', description: 'Import from Bitrix24 clicked' })
}
},
{
label: 'Import from Slack',
icon: SlackIcon,
to: 'https://slack.com',
target: '_blank',
onSelect(e: Event) {
e.preventDefault()
toast.add({ title: 'Action', description: 'Import from Slack clicked' })
}
}
]
}
]
]
},
{
label: 'New team',
icon: CirclePlusIcon,
kbds: ['meta', 'n'],
loading: loading.value,
onSelect(e: Event) {
e?.preventDefault()
if (loading.value) {
return
}
loading.value = true
const toastItem = toast.add({
icon: LoaderWaitIcon,
title: 'Action loading',
description: 'New team loading',
color: 'warning'
})
setTimeout(() => {
loading.value = false
toast.update(toastItem.id, {
icon: CircleCheckThinIcon,
title: 'Action stop',
description: 'New team loading stops',
color: 'success'
})
}, 2000)
}
}
],
[
{
label: 'GitHub',
to: 'https://github.com/bitrix24/b24ui',
target: '_blank',
onSelect(e: Event) {
e.preventDefault()
}
},
{
label: 'Support',
icon: PulseCircleIcon,
to: '/b24ui/components/dropdown-menu.html'
},
{
label: 'API',
icon: ItemIcon,
disabled: true
}
],
[
{
label: 'Logout',
icon: CrossCircle50Icon,
kbds: ['shift', 'meta', 'q'],
onSelect() {
toast.add({ title: 'Action', description: 'Logout clicked' })
}
}
]
])
</script>
<template>
<B24DropdownMenu
:items="items"
>
<B24Button label="Open" color="link" depth="dark" :icon="MenuIcon" />
<template #custom-trailing>
<CircleCheckThinIcon class="shrink-0 size-5 text-ai-500" />
</template>
</B24DropdownMenu>
</template>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
INFO
You can also pass an array of arrays to the items
prop to create separated groups of items.
TIP
Each item can take a children
array of objects with the same properties as the items
prop to create a nested menu which can be controlled using the open
, defaultOpen
and content
properties.
Content ​
Use the content
prop to control how the DropdownMenu content is rendered, like its align
or side
for example.
Details
<script setup lang="ts">
import { computed } from 'vue'
import MenuIcon from '@bitrix24/b24icons-vue/main/MenuIcon'
import PencilDrawIcon from '@bitrix24/b24icons-vue/actions/PencilDrawIcon'
import CopyPlatesIcon from '@bitrix24/b24icons-vue/actions/CopyPlatesIcon'
import OpenedEyeIcon from '@bitrix24/b24icons-vue/main/OpenedEyeIcon'
export interface ExampleProps {
contentAlign?: 'start' | 'center' | 'end'
contentSide?: 'top' | 'right' | 'bottom' | 'left'
contentSideOffset?: number
}
const props = withDefaults(defineProps<ExampleProps>(), {
contentAlign: 'start',
contentSide: 'left',
contentSideOffset: 8
})
const items = [
{
label: 'View',
icon: OpenedEyeIcon
},
{
label: 'Copy',
icon: CopyPlatesIcon
},
{
label: 'Edit',
icon: PencilDrawIcon
}
]
const content = computed(() => {
return {
align: props.contentAlign,
side: props.contentSide,
sideOffset: props.contentSideOffset
}
})
</script>
<template>
<B24DropdownMenu
:items="items"
:content="content"
>
<B24Button label="Open" color="link" depth="dark" :icon="MenuIcon" />
</B24DropdownMenu>
</template>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
Arrow ​
Use the arrow
prop to display an arrow on the DropdownMenu.
Details
<script setup lang="ts">
import MenuIcon from '@bitrix24/b24icons-vue/main/MenuIcon'
import PencilDrawIcon from '@bitrix24/b24icons-vue/actions/PencilDrawIcon'
import CopyPlatesIcon from '@bitrix24/b24icons-vue/actions/CopyPlatesIcon'
import OpenedEyeIcon from '@bitrix24/b24icons-vue/main/OpenedEyeIcon'
const items = [
{
label: 'View',
icon: OpenedEyeIcon
},
{
label: 'Copy',
icon: CopyPlatesIcon
},
{
label: 'Edit',
icon: PencilDrawIcon
}
]
</script>
<template>
<B24DropdownMenu
arrow
:items="items"
>
<B24Button label="Open" color="link" depth="dark" :icon="MenuIcon" />
</B24DropdownMenu>
</template>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
Size ​
Use the size
prop to control the size of the DropdownMenu.
WARNING
The size
prop will not be proxied to the Button, you need to set it yourself.
INFO
When using the same size, the DropdownMenu items will be perfectly aligned with the Button.
Details
<script setup lang="ts">
import type { DropdownMenuProps } from '@bitrix24/b24ui-nuxt'
import MenuIcon from '@bitrix24/b24icons-vue/main/MenuIcon'
import PencilDrawIcon from '@bitrix24/b24icons-vue/actions/PencilDrawIcon'
import CopyPlatesIcon from '@bitrix24/b24icons-vue/actions/CopyPlatesIcon'
import OpenedEyeIcon from '@bitrix24/b24icons-vue/main/OpenedEyeIcon'
export interface ExampleProps {
size?: DropdownMenuProps['size']
}
withDefaults(defineProps<ExampleProps>(), {
size: 'md' as const
})
const items = [
{
label: 'View',
icon: OpenedEyeIcon
},
{
label: 'Copy',
icon: CopyPlatesIcon
},
{
label: 'Edit',
icon: PencilDrawIcon
}
]
</script>
<template>
<B24DropdownMenu
:size="size"
:items="items"
>
<B24Button label="Open" color="link" depth="dark" :icon="MenuIcon" />
</B24DropdownMenu>
</template>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
Disabled ​
Use the disabled
prop to disable the DropdownMenu.
Details
<script setup lang="ts">
import MenuIcon from '@bitrix24/b24icons-vue/main/MenuIcon'
import PencilDrawIcon from '@bitrix24/b24icons-vue/actions/PencilDrawIcon'
import CopyPlatesIcon from '@bitrix24/b24icons-vue/actions/CopyPlatesIcon'
import OpenedEyeIcon from '@bitrix24/b24icons-vue/main/OpenedEyeIcon'
export interface ExampleProps {
isDisabled?: boolean
}
withDefaults(defineProps<ExampleProps>(), {
isDisabled: true
})
const items = [
{
label: 'View',
icon: OpenedEyeIcon
},
{
label: 'Copy',
icon: CopyPlatesIcon
},
{
label: 'Edit',
icon: PencilDrawIcon
}
]
</script>
<template>
<B24DropdownMenu
:disabled="isDisabled"
:items="items"
>
<B24Button label="Open" color="link" depth="dark" :icon="MenuIcon" />
</B24DropdownMenu>
</template>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
Examples ​
With checkbox items ​
You can use the type
property with checkbox
and use the checked
/ onUpdateChecked
properties to control the checked state of the item.
INFO
To ensure reactivity for the checked
state of items, it's recommended to wrap your items
array inside a computed
.
Details
<script setup lang="ts">
import { ref, computed } from 'vue'
import MenuIcon from '@bitrix24/b24icons-vue/main/MenuIcon'
import PencilDrawIcon from '@bitrix24/b24icons-vue/actions/PencilDrawIcon'
import CopyPlatesIcon from '@bitrix24/b24icons-vue/actions/CopyPlatesIcon'
import OpenedEyeIcon from '@bitrix24/b24icons-vue/main/OpenedEyeIcon'
const showCopy = ref(true)
const showEdit = ref(false)
const items = computed(() => [
{
label: 'View',
icon: OpenedEyeIcon,
type: 'label' as const
},
{
type: 'separator' as const
},
{
label: 'Copy',
icon: CopyPlatesIcon,
type: 'checkbox' as const,
checked: showCopy.value,
onUpdateChecked(checked: boolean) {
showCopy.value = checked
},
onSelect(e: Event) {
e.preventDefault()
}
},
{
label: 'Edit',
icon: PencilDrawIcon,
type: 'checkbox' as const,
checked: showEdit.value,
onUpdateChecked(checked: boolean) {
showEdit.value = checked
}
}
])
</script>
<template>
<B24DropdownMenu
:items="items"
>
<B24Button label="Open" color="link" depth="dark" :icon="MenuIcon" />
</B24DropdownMenu>
</template>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
With color items ​
You can use the color
property to highlight certain items with a color.
Details
<script setup lang="ts">
import TrashBinIcon from '@bitrix24/b24icons-vue/main/TrashBinIcon'
import PencilDrawIcon from '@bitrix24/b24icons-vue/actions/PencilDrawIcon'
import CopyPlatesIcon from '@bitrix24/b24icons-vue/actions/CopyPlatesIcon'
import OpenedEyeIcon from '@bitrix24/b24icons-vue/main/OpenedEyeIcon'
const items = [
[
{
label: 'View',
icon: OpenedEyeIcon
},
{
label: 'Copy',
icon: CopyPlatesIcon
},
{
label: 'Edit',
icon: PencilDrawIcon
}
],
[
{
label: 'Delete',
color: 'danger' as const,
icon: TrashBinIcon
}
]
]
</script>
<template>
<B24DropdownMenu
:items="items"
>
<B24Button label="Open" color="link" depth="dark" use-dropdown />
</B24DropdownMenu>
</template>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
Control open state ​
You can control the open state by using the default-open
prop or the v-model:open
directive.
INFO
In this example, leveraging defineShortcuts
, you can toggle the DropdownMenu by pressing O
.
Details
<script setup lang="ts">
import { ref } from 'vue'
import MenuIcon from '@bitrix24/b24icons-vue/main/MenuIcon'
import PencilDrawIcon from '@bitrix24/b24icons-vue/actions/PencilDrawIcon'
import CopyPlatesIcon from '@bitrix24/b24icons-vue/actions/CopyPlatesIcon'
import OpenedEyeIcon from '@bitrix24/b24icons-vue/main/OpenedEyeIcon'
const open = ref(false)
defineShortcuts({
o: () => open.value = !open.value
})
const items = [
{
label: 'View',
icon: OpenedEyeIcon
},
{
label: 'Copy',
icon: CopyPlatesIcon
},
{
label: 'Edit',
icon: PencilDrawIcon
}
]
</script>
<template>
<B24DropdownMenu
v-model:open="open"
:items="items"
:b24ui="{ content: 'w-52' }"
>
<B24Button label="Open" color="link" depth="dark" :icon="MenuIcon" />
</B24DropdownMenu>
</template>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
With custom slot ​
Use the slot
property to customize a specific item.
You will have access to the following slots:
#{{ item.slot }}
#{{ item.slot }}-leading
#{{ item.slot }}-label
#{{ item.slot }}-trailing
TIP
You can also use the #item
, #item-leading
, #item-label
and #item-trailing
slots to customize all items.
Details
<script setup lang="ts">
import MenuIcon from '@bitrix24/b24icons-vue/main/MenuIcon'
import PencilDrawIcon from '@bitrix24/b24icons-vue/actions/PencilDrawIcon'
import CopyPlatesIcon from '@bitrix24/b24icons-vue/actions/CopyPlatesIcon'
import OpenedEyeIcon from '@bitrix24/b24icons-vue/main/OpenedEyeIcon'
import BatteryIcon from '@bitrix24/b24icons-vue/button/BatteryIcon'
const items = [
{
label: 'View',
icon: OpenedEyeIcon,
slot: 'view'
},
{
label: 'Copy',
icon: CopyPlatesIcon
},
{
label: 'Edit',
icon: PencilDrawIcon
}
]
</script>
<template>
<B24DropdownMenu
:items="items"
:b24ui="{ content: 'w-52' }"
>
<B24Button label="Open" color="link" depth="dark" :icon="MenuIcon" />
<template #view-trailing>
<BatteryIcon class="shrink-0 size-5 text-ai-500" />
</template>
</B24DropdownMenu>
</template>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
Extract shortcuts ​
When you have some items with kbds
property (displaying some Kbd), you can easily make them work with the defineShortcuts composable.
Inside the defineShortcuts
composable, there is an extractShortcuts
utility that will extract the shortcuts recursively from the items and return an object that you can pass to defineShortcuts
. It will automatically call the select
function of the item when the shortcut is pressed.
<script setup lang="ts">
const items = [
{
label: 'Invite users',
children: [
{
label: 'Invite by email',
kbds: ['meta', 'e'],
onSelect() {
console.log('Invite by email clicked')
}
},
{
label: 'Invite by link',
kbds: ['meta', 'i'],
onSelect() { console.log('Invite by link clicked') }
}
]
},
{
label: 'New team',
kbds: ['meta', 'n'],
onSelect() { console.log('New team clicked') }
}
]
defineShortcuts(extractShortcuts(items))
</script>
INFO
On macOS in this example, ⌘
E
, ⌘
I
and ⌘
N
would trigger the select
function of the corresponding item.
On Windows in this example, ⊞
E
, ⊞
I
and ⊞
N
would trigger the select
function of the corresponding item.
API ​
Props ​
Prop | Default | Type |
---|---|---|
size | "lg" | "md" | "xs" | "sm" | |
items | DropdownMenuItem[] | DropdownMenuItem[][] | |
checkedIcon | icons.check = `CheckIcon` | (props: HTMLAttributes & VNodeProps & {}, ctx: Omit<{ attrs: Data; slots: Readonly<InternalSlots>; emit: (event: string, ...args: any[]) => void; expose: <Exposed extends Record<string, any> = Record<...>>(exposed?: Exposed) => void; }, "expose">): any The icon displayed when an item is checked. |
externalIcon | true | boolean | IconComponent The icon displayed when the item is an external link.
Set to `false` to hide the external icon. |
content | { side: 'bottom', sideOffset: 8, collisionPadding: 8 } | Omit<DropdownMenuContentProps, "as" | "asChild" | "forceMount"> The content of the menu. |
arrow | false | boolean | Omit<DropdownMenuArrowProps, "as" | "asChild"> Display an arrow alongside the menu. |
portal | true | boolean Render the menu in a portal. |
labelKey | "label" | string The key used to get the label from the item. |
disabled | boolean | |
b24ui | PartialString<{ content: string; arrow: string; group: string; label: string; separator: string; item: string; itemLeadingIcon: string; itemLeadingAvatar: string; itemLeadingAvatarSize: string; itemTrailing: string; ... 4 more ...; itemLabelExternalIcon: string; }> | |
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 `v-model:open`. | |
modal | true | boolean The modality of the dropdown menu.
When set to `true`, interaction with outside elements will be disabled and only menu content will be visible to screen readers. |
Slots ​
Slot | Type |
---|---|
default | { open: boolean; } |
item | { item: DropdownMenuItem; active?: boolean; index: number; } |
item-leading | { item: DropdownMenuItem; active?: boolean; index: number; } |
item-label | { item: DropdownMenuItem; active?: boolean; index: number; } |
item-trailing | { item: DropdownMenuItem; active?: boolean; index: number; } |
Emits ​
Event | Type |
---|