Usage
Use a v-model
to display a searchable and selectable list of commands.
<script setup>
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
: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>
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>
You can pass multiple groups of commands to the component. Each group will be separated by a divider and will display a label.
Without a v-model
, you can also listen on @update:model-value
to navigate to a link or do something else when a command is clicked.
Recent searches
<script setup>
const router = useRouter()
const toast = useToast()
const commandPaletteRef = ref()
const users = [
{ id: 'benjamincanac', label: 'benjamincanac', href: 'https://github.com/benjamincanac', target: '_blank', avatar: { src: 'https://avatars.githubusercontent.com/u/739984?v=4' } },
{ id: 'Atinux', label: 'Atinux', href: 'https://github.com/Atinux', target: '_blank', avatar: { src: 'https://avatars.githubusercontent.com/u/904724?v=4' } },
{ id: 'smarroufin', label: 'smarroufin', href: 'https://github.com/smarroufin', target: '_blank', avatar: { src: 'https://avatars.githubusercontent.com/u/7547335?v=4' } }
]
const actions = [
{ id: 'new-file', label: 'Add new file', icon: 'i-heroicons-document-plus', click: () => toast.add({ title: 'New file added!' }), shortcuts: ['⌘', 'N'] },
{ id: 'new-folder', label: 'Add new folder', icon: 'i-heroicons-folder-plus', click: () => toast.add({ title: 'New folder added!' }), shortcuts: ['⌘', 'F'] },
{ id: 'hashtag', label: 'Add hashtag', icon: 'i-heroicons-hashtag', click: () => toast.add({ title: 'Hashtag added!' }), shortcuts: ['⌘', 'H'] },
{ id: 'label', label: 'Add label', icon: 'i-heroicons-tag', click: () => toast.add({ title: 'Label added!' }), shortcuts: ['⌘', 'L'] }
]
const groups = computed(() =>
[commandPaletteRef.value?.query ? {
key: 'users',
commands: users
} : {
key: 'recent',
label: 'Recent searches',
commands: users.slice(0, 1)
}, {
key: 'actions',
commands: actions
}].filter(Boolean))
function onSelect (option) {
if (option.click) {
option.click()
} else if (option.to) {
router.push(option.to)
} else if (option.href) {
window.open(option.href, '_blank')
}
}
</script>
<template>
<UCommandPalette ref="commandPaletteRef" :groups="groups" @update:model-value="onSelect" />
</template>
Icon
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
.
We couldn't find any items.
<UCommandPalette icon="i-heroicons-command-line" />
Loading
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
.
We couldn't find any items.
<UCommandPalette loading />
Placeholder
Use the placeholder
prop to change the input placeholder
We couldn't find any items.
<UCommandPalette placeholder="Type a command..." />
Close
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
.
We couldn't find any items.
<UCommandPalette :close-button="{ icon: 'i-heroicons-x-mark-20-solid', color: 'gray', variant: 'link', padded: false }" />
Empty
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.
We couldn't find any items.
<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.' }" />
Full-text search
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>
Async search
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.
We couldn't find any items.
<script setup>
const groups = computed(() => {
return [{
key: 'users',
label: q => q && `Users matching “${q}”...`,
search: async (q) => {
if (!q) {
return []
}
const users = await $fetch(`https://jsonplaceholder.typicode.com/users`, { params: { q } })
return users.map(user => ({ id: user.id, label: user.name, suffix: user.email }))
}
}].filter(Boolean)
})
</script>
<template>
<UCommandPalette :groups="groups" />
</template>
loading
state will automatically be enabled when a search
function is loading. You can disable this behavior by setting the loading-icon
prop to null
or globally in ui.commandPalette.default.loadingIcon
.Slots
<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.
group
, command
, active
and selected
properties in the slot scope.empty-state
Use the #empty-state
slot to customize the empty state.
<script setup>
const groups = [...]
</script>
<template>
<UCommandPalette :groups="groups">
<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>
Props
undefined
"Search..."
config.default.icon
null
config.default.loadingIcon
"id"
config.default.selectedIcon
200
config.default.emptyState
"label"
"label"
[]
config.default.closeButton as Button
{}
false
false
false
true
true
true
Preset
undefined