Usage
Use the v-model directive to control the value of the CommandPalette or the default-value prop to set the initial value when you do not need to control its state.
<script setup lang="ts">
const groups = ref([
{
id: 'users',
label: 'Users',
items: [
{
label: 'Assistant Name',
suffix: 'assistant',
avatar: {
src: '/b24ui/avatar/assistant.png'
}
},
{
label: 'Bitrix24',
suffix: 'bitrix24',
avatar: {
src: 'https://github.com/bitrix24.png'
}
},
{
label: 'Employee Name',
suffix: 'employee',
avatar: {
src: '/b24ui/avatar/employee.png'
}
}
]
}
])
const value = ref({})
</script>
<template>
<B24CommandPalette v-model="value" :groups="groups" class="flex-1" />
</template>
Groups
The CommandPalette component filters groups and ranks matching commands by relevance as users type. It provides dynamic, instant search results for efficient command discovery. Use the groups prop as an array of objects with the following properties:
id: stringlabel?: stringslot?: stringitems?: CommandPaletteItem[]ignoreFilter?: booleanpostFilter?: (searchTerm: string, items: T[]) => T[]highlightedIcon?: IconComponent
id for each group otherwise the group will be ignored.Each group contains an items array of objects that define the commands. Each item can have the following properties:
prefix?: stringlabel?: stringsuffix?: stringicon?: IconComponentavatar?: AvatarPropschip?: ChipPropskbds?: string[] | KbdProps[]active?: booleanloading?: booleandisabled?: booleanslot?: stringplaceholder?: stringchildren?: CommandPaletteItem[]onSelect?: (e: Event) => voidclass?: anyb24ui?: { item?: ClassNameValue, itemLeadingIcon?: ClassNameValue, itemLeadingAvatarSize?: ClassNameValue, itemLeadingAvatar?: ClassNameValue, itemLeadingChipSize?: ClassNameValue, itemLeadingChip?: ClassNameValue, itemLabel?: ClassNameValue, itemLabelPrefix?: ClassNameValue, itemLabelBase?: ClassNameValue, itemLabelSuffix?: ClassNameValue, itemTrailing?: ClassNameValue, itemTrailingKbds?: ClassNameValue, itemTrailingKbdsSize?: ClassNameValue, itemTrailingHighlightedIcon?: ClassNameValue, itemTrailingIcon?: ClassNameValue }
You can pass any property from the Link component such as to, target, etc.
<script setup lang="ts">
const groups = ref([
{
id: 'users',
label: 'Users',
items: [
{
label: 'Assistant Name',
suffix: 'assistant',
avatar: {
src: '/b24ui/avatar/assistant.png'
}
},
{
label: 'Bitrix24',
suffix: 'bitrix24',
avatar: {
src: 'https://github.com/bitrix24.png'
}
},
{
label: 'Employee Name',
suffix: 'employee',
avatar: {
src: '/b24ui/avatar/employee.png'
}
}
]
}
])
const value = ref({})
</script>
<template>
<B24CommandPalette v-model="value" :groups="groups" class="flex-1" />
</template>
Multiple
Use the multiple prop to allow multiple selections.
<script setup lang="ts">
const groups = ref([
{
id: 'users',
label: 'Users',
items: [
{
label: 'Assistant Name',
suffix: 'assistant',
avatar: {
src: '/b24ui/avatar/assistant.png'
}
},
{
label: 'Bitrix24',
suffix: 'bitrix24',
avatar: {
src: 'https://github.com/bitrix24.png'
}
},
{
label: 'Employee Name',
suffix: 'employee',
avatar: {
src: '/b24ui/avatar/employee.png'
}
}
]
}
])
const value = ref([])
</script>
<template>
<B24CommandPalette multiple v-model="value" :groups="groups" class="flex-1" />
</template>
default-value prop or the v-model directive.Placeholder
Use the placeholder prop to change the placeholder text.
<script setup lang="ts">
const groups = ref([
{
id: 'apps',
items: [
{
label: 'Calendar'
},
{
label: 'Music'
},
{
label: 'Maps'
}
]
}
])
</script>
<template>
<B24CommandPalette placeholder="Search an app..." :groups="groups" class="flex-1" />
</template>
Icon
Use the icon prop to customize the input Icon.
<script setup lang="ts">
import RocketIcon from '@bitrix24/b24icons-vue/main/RocketIcon'
const groups = ref([
{
id: 'apps',
items: [
{
label: 'Calendar'
},
{
label: 'Music'
},
{
label: 'Maps'
}
]
}
])
</script>
<template>
<B24CommandPalette :icon="RocketIcon" :groups="groups" class="flex-1" />
</template>
Selected Icon
Use the selected-icon prop to customize the selected item Icon.
<script setup lang="ts">
import RocketIcon from '@bitrix24/b24icons-vue/main/RocketIcon'
const groups = ref([
{
id: 'users',
label: 'Users',
items: [
{
label: 'Assistant Name',
suffix: 'assistant',
avatar: {
src: '/b24ui/avatar/assistant.png'
}
},
{
label: 'Bitrix24',
suffix: 'bitrix24',
avatar: {
src: 'https://github.com/bitrix24.png'
}
},
{
label: 'Employee Name',
suffix: 'employee',
avatar: {
src: '/b24ui/avatar/employee.png'
}
}
]
}
])
const value = ref([
{
label: 'Bitrix24',
suffix: 'bitrix24',
avatar: {
src: 'https://github.com/bitrix24.png'
}
}
])
</script>
<template>
<B24CommandPalette multiple v-model="value" :selected-icon="RocketIcon" :groups="groups" class="flex-1" />
</template>
Trailing Icon
Use the trailing-icon prop to customize the trailing Icon when an item has children.
<script setup lang="ts">
import RocketIcon from '@bitrix24/b24icons-vue/main/RocketIcon'
const groups = ref([
{
id: 'actions',
items: [
{
label: 'Share',
children: [
{
label: 'Email'
},
{
label: 'Copy'
},
{
label: 'Link'
}
]
}
]
}
])
</script>
<template>
<B24CommandPalette :trailing-icon="RocketIcon" :groups="groups" class="flex-1" />
</template>
Loading
Use the loading prop to show a loading icon on the CommandPalette.
<script setup lang="ts">
const groups = ref([
{
id: 'apps',
items: [
{
label: 'Calendar'
},
{
label: 'Music'
},
{
label: 'Maps'
}
]
}
])
</script>
<template>
<B24CommandPalette loading :groups="groups" class="flex-1" />
</template>
Close
Use the close prop to display a Button to dismiss the CommandPalette.
update:open event will be emitted when the close button is clicked.<script setup lang="ts">
const groups = ref([
{
id: 'apps',
items: [
{
label: 'Calendar'
},
{
label: 'Music'
},
{
label: 'Maps'
}
]
}
])
</script>
<template>
<B24CommandPalette close :groups="groups" class="flex-1" />
</template>
You can pass any property from the Button component to customize it.
<script setup lang="ts">
const groups = ref([
{
id: 'apps',
items: [
{
label: 'Calendar'
},
{
label: 'Music'
},
{
label: 'Maps'
}
]
}
])
</script>
<template>
<B24CommandPalette
:close="{
color: 'air-primary',
rounded: true,
size: 'md'
}"
:groups="groups"
class="flex-1"
/>
</template>
Close Icon
Use the close-icon prop to customize the close button Icon.
<script setup lang="ts">
import RocketIcon from '@bitrix24/b24icons-vue/main/RocketIcon'
const groups = ref([
{
id: 'apps',
items: [
{
label: 'Calendar'
},
{
label: 'Music'
},
{
label: 'Maps'
}
]
}
])
</script>
<template>
<B24CommandPalette close :close-icon="RocketIcon" :groups="groups" class="flex-1" />
</template>
Back
Use the back prop to customize or hide the back button (with false value) displayed when navigating into a submenu.
You can pass any property from the Button component to customize it.
<script setup lang="ts">
const groups = ref([
{
id: 'actions',
items: [
{
label: 'Share',
children: [
{
label: 'Email'
},
{
label: 'Copy'
},
{
label: 'Link'
}
]
}
]
}
])
</script>
<template>
<B24CommandPalette
:back="{
color: 'air-primary'
}"
:groups="groups"
class="flex-1"
/>
</template>
Back Icon
Use the back-icon prop to customize the back button Icon.
<script setup lang="ts">
import RocketIcon from '@bitrix24/b24icons-vue/main/RocketIcon'
const groups = ref([
{
id: 'actions',
items: [
{
label: 'Share',
children: [
{
label: 'Email'
},
{
label: 'Copy'
},
{
label: 'Link'
}
]
}
]
}
])
</script>
<template>
<B24CommandPalette :back-icon="RocketIcon" :groups="groups" class="flex-1" />
</template>
Disabled
Use the disabled prop to disable the CommandPalette.
<script setup lang="ts">
const groups = ref([
{
id: 'apps',
items: [
{
label: 'Calendar'
},
{
label: 'Music'
},
{
label: 'Maps'
}
]
}
])
</script>
<template>
<B24CommandPalette disabled :groups="groups" class="flex-1" />
</template>
Examples
Control selected item(s)
You can control the selected item(s) by using the default-value prop or the v-model directive, by using the onSelect field on each item or by using the @update:model-value event.
Control search term
Use the v-model:search-term directive to control the search term.
@update:model-value event to reset the search term when an item is selected.With children in items
You can create hierarchical menus by using the children property in items. When an item has children, it will automatically display a chevron icon and enable navigation into a submenu.
- The search term is reset
- A back button appears in the input
- You can go back to the previous group by pressing the ⌫ key
With fetched items
You can fetch items from an API and use them in the CommandPalette.
With ignore filter
You can set the ignoreFilter field to true on a group to disable the internal search and use your own search logic.
refDebounced to debounce the API calls.With post-filtered items
You can use the postFilter field on a group to filter items after the search happened.
With custom fuse search
You can use the fuse prop to override the options of useFuse which defaults to:
{
fuseOptions: {
ignoreLocation: true,
threshold: 0.1,
keys: ['label', 'suffix']
},
resultLimit: 12,
matchAllWhenSearchEmpty: true
}
fuseOptions are the options of Fuse.js, the resultLimit is the maximum number of results to return and the matchAllWhenSearchEmpty is a boolean to match all items when the search term is empty.You can for example set { fuseOptions: { includeMatches: true } } to highlight the search term in the items.
With virtualization
Use the virtualize prop to enable virtualization for large lists as a boolean or an object with options like { estimateSize: 32, overscan: 12 }.
Within a Popover
You can use the CommandPalette component inside a Popover's content.
Within a Modal
You can use the CommandPalette component inside a Modal's content.
Listen open state
When using the close prop, you can listen to the update:open event when the button is clicked.
Modal for example.With footer slot
Use the #footer slot to add custom content at the bottom of the CommandPalette, such as keyboard shortcuts help or additional actions.
With custom slot
Use the slot property to customize a specific item or group.
You will have access to the following slots:
#{{ item.slot }}#{{ item.slot }}-leading#{{ item.slot }}-label#{{ item.slot }}-trailing#{{ group.slot }}#{{ group.slot }}-leading#{{ group.slot }}-label#{{ group.slot }}-trailing
#item, #item-leading, #item-label and #item-trailing slots to customize all items.API
Props
Slots
Emits
Theme
export default defineAppConfig({
b24ui: {
commandPalette: {
slots: {
root: 'flex flex-col min-h-0 min-w-0 divide-y divide-(--ui-color-design-tinted-na-stroke)',
input: 'ps-[40px] pe-[44px]',
close: '',
back: 'p-0',
content: 'relative overflow-hidden flex flex-col',
footer: 'p-1',
viewport: 'relative scroll-py-1 overflow-y-auto scrollbar-thin flex-1 focus:outline-none',
group: 'p-1 isolate',
empty: 'py-6 text-center text-(length:--ui-font-size-sm) text-(--b24ui-typography-description-color)',
label: 'p-[6px] text-(length:--ui-font-size-xs) text-(--b24ui-typography-label-color)',
item: 'group relative w-full flex items-center gap-[6px] p-[6px] text-(length:--ui-font-size-sm) select-none outline-none before:absolute before:z-[-1] before:inset-px before:rounded-(--ui-border-radius-sm) data-disabled:cursor-not-allowed data-disabled:opacity-30',
itemLeadingIcon: 'shrink-0 size-[20px]',
itemLeadingAvatar: 'shrink-0',
itemLeadingAvatarSize: '2xs',
itemLeadingChip: 'shrink-0 size-[20px]',
itemLeadingChipSize: 'md',
itemTrailing: 'ms-auto inline-flex gap-[6px] items-center',
itemTrailingIcon: 'shrink-0 size-[20px] text-(--ui-color-accent-main-primary)',
itemTrailingHighlightedIcon: 'shrink-0 size-[20px] text-(--b24ui-typography-label-color) hidden group-data-highlighted:inline-flex',
itemTrailingKbds: 'hidden lg:inline-flex items-center shrink-0 gap-0.5',
itemTrailingKbdsSize: 'md',
itemWrapper: 'flex-1 flex flex-col text-start min-w-0 overflow-hidden',
itemLabel: 'truncate space-x-1 text-(--b24ui-typography-label-color)',
itemDescription: 'truncate -mt-[6px] text-(--b24ui-typography-description-color) text-(length:--ui-font-size-sm)',
itemLabelBase: 'text-(--b24ui-typography-label-color) [&>mark]:text-(--ui-color-black-base) [&>mark]:bg-(--ui-color-collab-accent-less-1)',
itemLabelPrefix: 'text-(--b24ui-typography-legend-color)',
itemLabelSuffix: 'truncate text-(--b24ui-typography-description-color) [&>mark]:text-(--ui-color-black-base) [&>mark]:bg-(--ui-color-collab-accent-less-1)'
},
variants: {
virtualize: {
true: {
viewport: 'p-1 isolate'
},
false: {
viewport: ''
}
},
active: {
true: {
item: 'text-(--b24ui-typography-label-color) before:bg-(--ui-color-base-8)',
itemLeadingIcon: 'text-(--b24ui-typography-legend-color)'
},
false: {
item: 'text-(--b24ui-typography-legend-color) data-highlighted:not-data-disabled:text-(--b24ui-typography-legend-color) data-highlighted:not-data-disabled:before:bg-(--ui-color-bg-content-secondary) transition-colors before:transition-colors',
itemLeadingIcon: 'text-(--b24ui-typography-legend-color) group-data-highlighted:not-group-data-disabled:text-(--b24ui-typography-legend-color) transition-colors'
}
},
loading: {
true: {
itemLeadingIcon: 'animate-spin'
}
}
}
}
}
})
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import bitrix24UIPluginVite from '@bitrix24/b24ui-nuxt/vite'
export default defineConfig({
plugins: [
vue(),
bitrix24UIPluginVite({
b24ui: {
commandPalette: {
slots: {
root: 'flex flex-col min-h-0 min-w-0 divide-y divide-(--ui-color-design-tinted-na-stroke)',
input: 'ps-[40px] pe-[44px]',
close: '',
back: 'p-0',
content: 'relative overflow-hidden flex flex-col',
footer: 'p-1',
viewport: 'relative scroll-py-1 overflow-y-auto scrollbar-thin flex-1 focus:outline-none',
group: 'p-1 isolate',
empty: 'py-6 text-center text-(length:--ui-font-size-sm) text-(--b24ui-typography-description-color)',
label: 'p-[6px] text-(length:--ui-font-size-xs) text-(--b24ui-typography-label-color)',
item: 'group relative w-full flex items-center gap-[6px] p-[6px] text-(length:--ui-font-size-sm) select-none outline-none before:absolute before:z-[-1] before:inset-px before:rounded-(--ui-border-radius-sm) data-disabled:cursor-not-allowed data-disabled:opacity-30',
itemLeadingIcon: 'shrink-0 size-[20px]',
itemLeadingAvatar: 'shrink-0',
itemLeadingAvatarSize: '2xs',
itemLeadingChip: 'shrink-0 size-[20px]',
itemLeadingChipSize: 'md',
itemTrailing: 'ms-auto inline-flex gap-[6px] items-center',
itemTrailingIcon: 'shrink-0 size-[20px] text-(--ui-color-accent-main-primary)',
itemTrailingHighlightedIcon: 'shrink-0 size-[20px] text-(--b24ui-typography-label-color) hidden group-data-highlighted:inline-flex',
itemTrailingKbds: 'hidden lg:inline-flex items-center shrink-0 gap-0.5',
itemTrailingKbdsSize: 'md',
itemWrapper: 'flex-1 flex flex-col text-start min-w-0 overflow-hidden',
itemLabel: 'truncate space-x-1 text-(--b24ui-typography-label-color)',
itemDescription: 'truncate -mt-[6px] text-(--b24ui-typography-description-color) text-(length:--ui-font-size-sm)',
itemLabelBase: 'text-(--b24ui-typography-label-color) [&>mark]:text-(--ui-color-black-base) [&>mark]:bg-(--ui-color-collab-accent-less-1)',
itemLabelPrefix: 'text-(--b24ui-typography-legend-color)',
itemLabelSuffix: 'truncate text-(--b24ui-typography-description-color) [&>mark]:text-(--ui-color-black-base) [&>mark]:bg-(--ui-color-collab-accent-less-1)'
},
variants: {
virtualize: {
true: {
viewport: 'p-1 isolate'
},
false: {
viewport: ''
}
},
active: {
true: {
item: 'text-(--b24ui-typography-label-color) before:bg-(--ui-color-base-8)',
itemLeadingIcon: 'text-(--b24ui-typography-legend-color)'
},
false: {
item: 'text-(--b24ui-typography-legend-color) data-highlighted:not-data-disabled:text-(--b24ui-typography-legend-color) data-highlighted:not-data-disabled:before:bg-(--ui-color-bg-content-secondary) transition-colors before:transition-colors',
itemLeadingIcon: 'text-(--b24ui-typography-legend-color) group-data-highlighted:not-group-data-disabled:text-(--b24ui-typography-legend-color) transition-colors'
}
},
loading: {
true: {
itemLeadingIcon: 'animate-spin'
}
}
}
}
}
})
]
})