Add a customizable command palette to your app.
Use a v-model
to display a searchable and selectable list of commands.
<script setup lang="ts">
const people = [
{ id: 1, label: 'Wade Cooper' },
{ id: 2, label: 'Arlene Mccoy' },
{ id: 3, label: 'Devon Webb' },
{ id: 4, label: 'Tom Cook' },
{ id: 5, label: 'Tanya Fox' },
{ id: 6, label: 'Hellen Schmidt' },
{ id: 7, label: 'Caroline Schultz' },
{ id: 8, label: 'Mason Heaney' },
{ id: 9, label: 'Claudie Smitham' },
{ id: 10, label: 'Emil Schaefer' }
]
const selected = ref([people[3]])
</script>
<template>
<UCommandPalette
v-model="selected"
multiple
nullable
:autoselect="false"
:groups="[{ key: 'people', commands: people }]"
:fuse="{ resultLimit: 6, fuseOptions: { threshold: 0.1 } }"
/>
</template>
You can put a CommandPalette
anywhere you want but it’s most commonly used inside of a modal.
<script setup lang="ts">
const isOpen = ref(false)
const people = [
{ id: 1, label: 'Wade Cooper' },
{ id: 2, label: 'Arlene Mccoy' },
{ id: 3, label: 'Devon Webb' },
{ id: 4, label: 'Tom Cook' },
{ id: 5, label: 'Tanya Fox' },
{ id: 6, label: 'Hellen Schmidt' },
{ id: 7, label: 'Caroline Schultz' },
{ id: 8, label: 'Mason Heaney' },
{ id: 9, label: 'Claudie Smitham' },
{ id: 10, label: 'Emil Schaefer' }
]
const selected = ref([])
</script>
<template>
<div>
<UButton label="Open" @click="isOpen = true" />
<UModal v-model="isOpen">
<UCommandPalette
v-model="selected"
multiple
nullable
:groups="[{ key: 'people', commands: people }]"
/>
</UModal>
</div>
</template>
Use any icon from Iconify by setting the icon
prop by using this pattern: i-{collection_name}-{icon_name}
.
Use the selected-icon
prop to set a different icon or change it globally in ui.commandPalette.default.selectedIcon
. Defaults to i-heroicons-check-20-solid
.
<template>
<UCommandPalette icon="i-heroicons-command-line" />
</template>
Use the loading
prop to show a loading icon.
Use the loading-icon
prop to set a different icon or change it globally in ui.commandPalette.default.loadingIcon
. Defaults to i-heroicons-arrow-path-20-solid
.
<template>
<UCommandPalette loading />
</template>
Use the placeholder
prop to change the input placeholder
<template>
<UCommandPalette placeholder="Type a command..." />
</template>
Use the close-button
prop to display a close button on the right side of the input.
You can pass all the props of the Button component to customize it through the close-button
prop or globally through ui.commandPalette.default.closeButton
.
<template>
<UCommandPalette
:close-button="{ icon: 'i-heroicons-x-mark-20-solid', color: 'gray', variant: 'link', padded: false }"
/>
</template>
An empty state will be displayed when there are no results.
Use the empty-state
prop to customize the icon
and label
or change them globally in ui.commandPalette.default.emptyState
.
You can also set it to null
to hide the empty state.
<template>
<UCommandPalette
:empty-state="{ icon: 'i-heroicons-magnifying-glass-20-solid', label: 'We couldn't find any items.', queryLabel: 'We couldn't find any items with that term. Please try again.' }"
placeholder="Type something to see the empty label change"
/>
</template>
The CommandPalette component takes care of the full-text search for you with Fuse.js. You can pass all the options of Fuse.js through the fuse
prop.
When searching for a command, the component will look for a label
property on the command by default. You can customize this behavior by overriding the command-attribute
prop. This will also affect the display of the command.
You can also highlight the matches in the command by setting the fuse.fuseOptions.includeMatches
to true
. The CommandPalette component automatically takes care of the highlighting for you.
<template>
<UCommandPalette
command-attribute="title"
:fuse="{
fuseOptions: {
ignoreLocation: true,
includeMatches: true,
threshold: 0,
keys: ['title', 'description', 'children.children.value', 'children.children.children.value']
},
resultLimit: 10
}"
/>
</template>
Try it yourself in this documentation’s search by pressing K.
You can also pass an async
function to the search
property of a group to perform an async search. The function will receive the query as its first argument and should return an array of commands.
<script setup lang="ts">
const groups = [{
key: 'users',
label: q => q && `Users matching "${q}"...`,
search: async (q) => {
if (!q) {
return []
}
// @ts-ignore
const users: any[] = await $fetch('https://jsonplaceholder.typicode.com/users', { params: { q } })
return users.map(user => ({ id: user.id, label: user.name, suffix: user.email }))
}
}]
</script>
<template>
<UCommandPalette :groups="groups" :autoselect="false" />
</template>
The
loading
state will automatically be enabled when asearch
function is loading. You can disable this behavior by setting theloading-icon
prop tonull
or globally inui.commandPalette.default.loadingIcon
.
You can also pass a function to the filter
property of a group to filter displayed commands after the search happened. The function will receive the query as its first argument, the array of commands as second argument and should return an array of commands.
<script setup lang="ts">
const people = [
{ id: 1, label: 'Wade Cooper', child: true },
{ id: 2, label: 'Arlene Mccoy' },
{ id: 3, label: 'Devon Webb', child: true },
{ id: 4, label: 'Tom Cook' },
{ id: 5, label: 'Tanya Fox', child: true },
{ id: 6, label: 'Hellen Schmidt' },
{ id: 7, label: 'Caroline Schultz', child: true },
{ id: 8, label: 'Mason Heaney' },
{ id: 9, label: 'Claudie Smitham', child: true },
{ id: 10, label: 'Emil Schaefer' }
]
const groups = [{
key: 'users',
commands: people,
filter: (q, commands) => {
if (!q) {
return commands?.filter(command => !command.child)
}
return commands
}
}]
</script>
<template>
<UCommandPalette :groups="groups" :autoselect="false" />
</template>
<group>-icon
Use the #<group>-icon
slot to override the left command content which display by default the icon
, avatar
and chip
.
<group>-command
Use the #<group>-command
slot to override the command content which display by default the prefix
, suffix
and label
(customizable through the command-attribute
prop).
<group>-active
Use the #<group>-active
slot to override the right command content (when hovered) which display by default the active
field of the group if provided.
<group>-inactive
Use the #<group>-inactive
slot to override the right command content (when not hovered) which display by default the inactive
field of the group if provided or the shortcuts
of the command.
The 4 slots above will have access to the
group
,command
,active
andselected
properties in the slot scope.
empty-state
Use the #empty-state
slot to customize the empty state.
<template>
<UCommandPalette>
<template #empty-state>
<div class="flex flex-col items-center justify-center py-6 gap-3">
<span class="italic text-sm">Nothing here!</span>
<UButton label="Add item" />
</div>
</template>
</UCommandPalette>
</template>
Refer to the props documentation for a complete list of available props.
When accessing the component via a template ref, you can use the following:
Refer to the API documentation for available methods and properties.
Refer to the configuration documentation for customizing the component’s appearance.
Here are a few examples illustrating how you can customize the appearance of the CommandPalette
component by utilizing its ui
prop.