CommandPalette
A searchable list of commands in a dialog. Compose CommandPaletteInput, CommandPaletteList, CommandPaletteGroup, CommandPaletteItem, CommandPaletteEmpty and CommandPaletteFooter inside the CommandPalette root. The app writes the rows; the palette owns the dialog, the query, the keyboard and the filter.
Groups and items go inside CommandPaletteList, which is the list itself and the only part that scrolls. The field, the empty state and the footer are its siblings: a list may own rows and groups and nothing else, and keeping them outside it is also what stops them scrolling away.
<CommandPalette v-model:open="open" @select="select">
<CommandPaletteInput placeholder="Search commands" />
<CommandPaletteList>
<CommandPaletteGroup label="Pages">
<CommandPaletteItem :value="page">Inbox</CommandPaletteItem>
</CommandPaletteGroup>
</CommandPaletteList>
<CommandPaletteEmpty>No matches</CommandPaletteEmpty>
<CommandPaletteFooter><KeyboardShortcut combo="Enter" /> to run</CommandPaletteFooter>
</CommandPalette>Experimental — the family ships from
frappe-ui/experimentalwhile its API settles, so it is exempt from the usual deprecation policy and can change shape or disappear in any release. The rootCommandPalettewas removed in1.0.0; see the migration guide.
import {
CommandPalette,
CommandPaletteInput,
CommandPaletteList,
CommandPaletteGroup,
CommandPaletteItem,
CommandPaletteEmpty,
CommandPaletteFooter,
} from 'frappe-ui/experimental'<script setup lang="ts">
import { ref } from 'vue'
import { Button, KeyboardShortcut, useKeyboardShortcut } from 'frappe-ui'
import {
CommandPalette,
CommandPaletteEmpty,
CommandPaletteFooter,
CommandPaletteGroup,
CommandPaletteInput,
CommandPaletteList,
CommandPaletteItem,
} from '..'
import type { CommandPaletteValue } from '..'
// The client filter runs by default, so this list is written once and the
// palette narrows it as the user types.
const pages = [
{ name: 'inbox', title: 'Inbox', icon: 'lucide-inbox', keywords: ['mail'] },
{ name: 'people', title: 'People', icon: 'lucide-users' },
{ name: 'settings', title: 'Settings', icon: 'lucide-settings' },
]
const actions = [
{
name: 'new-task',
title: 'New task',
icon: 'lucide-plus',
combo: 'Mod+N',
},
{
name: 'new-note',
title: 'New note',
icon: 'lucide-file-text',
combo: 'Mod+Shift+N',
},
]
const open = ref(false)
const picked = ref('')
// The palette no longer registers a shortcut. The app decides when Mod+K
// belongs to it.
useKeyboardShortcut({
combo: 'Mod+K',
description: 'Open command palette',
allowInInput: true,
handler: () => (open.value = true),
})
// `select` hands back exactly the object the item carried, typed as the
// palette's value union, so the handler narrows it.
function select(value: CommandPaletteValue) {
picked.value = (value as { title: string }).title
}
</script>
<template>
<div class="flex flex-col items-start gap-3">
<Button @click="open = true">Open command palette (or press Mod+K)</Button>
<p v-if="picked" class="text-p-sm text-ink-gray-6">Picked: {{ picked }}</p>
<CommandPalette v-model:open="open" @select="select">
<CommandPaletteInput placeholder="Search commands" />
<CommandPaletteList>
<CommandPaletteGroup label="Pages">
<CommandPaletteItem
v-for="page in pages"
:key="page.name"
:value="page"
:keywords="page.keywords"
>
<template #prefix>
<span :class="[page.icon, 'mr-3 size-4 text-ink-gray-7']" />
</template>
{{ page.title }}
</CommandPaletteItem>
</CommandPaletteGroup>
<CommandPaletteGroup label="Actions">
<CommandPaletteItem
v-for="action in actions"
:key="action.name"
:value="action"
>
<template #prefix>
<span :class="[action.icon, 'mr-3 size-4 text-ink-gray-7']" />
</template>
{{ action.title }}
<template #suffix>
<KeyboardShortcut :combo="action.combo" />
</template>
</CommandPaletteItem>
</CommandPaletteGroup>
</CommandPaletteList>
<CommandPaletteEmpty v-slot="{ query }">
Nothing matches "{{ query }}"
</CommandPaletteEmpty>
<CommandPaletteFooter>
<KeyboardShortcut combo="Enter" /> to run
<KeyboardShortcut combo="Escape" /> to close
</CommandPaletteFooter>
</CommandPalette>
</div>
</template>Opening it
The palette registers no shortcut. Write the one line yourself, so the app decides when Mod+K belongs to the palette and when it belongs to a focused editor:
useKeyboardShortcut({
combo: 'Mod+K',
description: 'Open command palette',
// Guards are off by default, so without this the shortcut dies as soon as
// any field has focus.
allowInInput: true,
handler: () => (open.value = true),
})Filtering
filterable is on by default. Each item matches when the query is a substring of its text, the same rule Combobox applies to its options.
An item filters on the text it renders in its default slot. #prefix and #suffix are left out, so a trailing shortcut hint or badge never becomes searchable. Add keywords for aliases the row does not show, and set label when the default slot draws more than the label.
<CommandPaletteItem :value="page" :keywords="['mail', 'unread']">
Inbox
<template #suffix><KeyboardShortcut combo="Mod+I" /></template>
</CommandPaletteItem>A group hides itself, heading and all, once the filter empties it.
Server-side search
Set :filterable="false" and refetch on update:query. The backend has already decided what matches, so a second pass on the client would drop its fuzzy and relevance-ranked rows.
<script setup lang="ts">
import { ref, watch } from 'vue'
import { Button } from 'frappe-ui'
import {
CommandPalette,
CommandPaletteEmpty,
CommandPaletteGroup,
CommandPaletteInput,
CommandPaletteList,
CommandPaletteItem,
} from '..'
// `:filterable="false"` hands the matching to the server. Without it, a
// second literal substring pass on the client would drop the fuzzy and
// relevance-ranked rows the backend just returned (ADR-0009).
const everything = [
{ name: 'design-review', title: 'Design review', team: 'Product' },
{ name: 'release-plan', title: 'Release plan', team: 'Engineering' },
{ name: 'onboarding', title: 'Onboarding checklist', team: 'People' },
{ name: 'q3-budget', title: 'Q3 budget', team: 'Finance' },
]
const open = ref(false)
const query = ref('')
const results = ref<typeof everything>([])
const loading = ref(false)
let timer: ReturnType<typeof setTimeout> | undefined
// A debounced refetch stands in for the real request.
watch(query, (text) => {
clearTimeout(timer)
if (!text) {
results.value = []
loading.value = false
return
}
loading.value = true
timer = setTimeout(() => {
const needle = text.toLowerCase()
results.value = everything.filter(
(row) =>
row.title.toLowerCase().includes(needle) ||
row.team.toLowerCase().includes(needle),
)
loading.value = false
}, 300)
})
</script>
<template>
<div class="flex flex-col items-start gap-3">
<Button @click="open = true">Search the server</Button>
<CommandPalette
v-model:open="open"
v-model:query="query"
:filterable="false"
>
<CommandPaletteInput placeholder="Search documents" />
<!-- The palette's own slot is open, so a loading row needs no extra
part. It sits outside the list, which owns options and groups only. -->
<div
v-if="loading"
class="px-4.5 py-8 text-center text-base text-ink-gray-5"
>
Searching…
</div>
<CommandPaletteList v-else>
<CommandPaletteGroup label="Documents">
<CommandPaletteItem
v-for="row in results"
:key="row.name"
:value="row"
>
{{ row.title }}
<template #suffix>
<span class="text-ink-gray-5">{{ row.team }}</span>
</template>
</CommandPaletteItem>
</CommandPaletteGroup>
</CommandPaletteList>
<CommandPaletteEmpty v-if="!loading" v-slot="{ query: text }">
{{ text ? `No documents match "${text}"` : 'Type to search' }}
</CommandPaletteEmpty>
</CommandPalette>
</div>
</template>Items that are links
Give an item as="a" and an href and it renders a real anchor, so middle-click and modifier-click open a new tab natively. select carries the click that picked the row in event.detail.originalEvent, which is where the modifier keys are.
<script setup lang="ts">
import { ref } from 'vue'
import { Button } from 'frappe-ui'
import {
CommandPalette,
CommandPaletteEmpty,
CommandPaletteGroup,
CommandPaletteInput,
CommandPaletteList,
CommandPaletteItem,
} from '..'
import type { CommandPaletteSelectEvent, CommandPaletteValue } from '..'
// `as="a"` plus `href` makes the row a real link, so middle-click,
// Cmd-click and "open in a new tab" all work the way the browser does
// them. Nothing here re-implements that.
const docs = [
{ link: '/docs/components/button', text: 'Button' },
{ link: '/docs/components/dialog', text: 'Dialog' },
{ link: '/docs/components/combobox', text: 'Combobox' },
]
const open = ref(false)
const visited = ref('')
function select(value: CommandPaletteValue, event: CommandPaletteSelectEvent) {
const item = value as { link: string }
const click = event.detail.originalEvent
// Let the browser take modifier-clicks through the `href`.
if (click.metaKey || click.ctrlKey || click.shiftKey || click.button === 1) {
return
}
click.preventDefault()
visited.value = item.link
}
</script>
<template>
<div class="flex flex-col items-start gap-3">
<Button @click="open = true">Search the docs</Button>
<p v-if="visited" class="text-p-sm text-ink-gray-6">
Would navigate to {{ visited }}
</p>
<CommandPalette v-model:open="open" @select="select">
<CommandPaletteInput placeholder="Search documentation" />
<CommandPaletteList>
<CommandPaletteGroup label="Components">
<CommandPaletteItem
v-for="page in docs"
:key="page.link"
as="a"
:href="page.link"
:value="page"
>
{{ page.text }}
</CommandPaletteItem>
</CommandPaletteGroup>
</CommandPaletteList>
<CommandPaletteEmpty />
</CommandPalette>
</div>
</template>Keeping it open
The palette closes after a pick. Call event.preventDefault() in the select handler to keep it open, for a row that switches the palette into a mode instead of running a command.
function select(value, event) {
if (value.kind === 'mode') {
event.preventDefault()
mode.value = value.name
}
}Styling hooks
Every part stamps data-slot. An item adds data-state="active" while the keyboard or the pointer is on it, and data-disabled when it cannot be picked. Items hand active and disabled to every one of their slots.
There is no selected state. A pick closes the palette, and a pick that keeps it open does so by preventing the event, which is the same signal that tells the list not to record the row.
API Reference
CommandPalette
Show types
import type { AcceptableValue } from 'reka-ui'
import type { Component } from 'vue'
/**
* A value a `CommandPaletteItem` can carry. The palette hands it back
* untouched in `select`, so most apps pass their own command object.
*/
export type CommandPaletteValue = AcceptableValue
/**
* The event `CommandPalette` and `CommandPaletteItem` emit on `select`.
*
* `detail.originalEvent` is the click that picked the item, so a caller can
* read `metaKey`, `ctrlKey`, `shiftKey` and `button`. Call `preventDefault()`
* on the event itself to keep the palette open.
*/
export type CommandPaletteSelectEvent = CustomEvent<{
originalEvent: PointerEvent
value?: CommandPaletteValue
}>
export interface CommandPaletteProps {
/**
* Filter the items against the query on the client. Set it to `false` when a
* server search already decided what matches (ADR-0009), then refetch on
* `update:query` yourself.
*/
filterable?: boolean
/**
* The dialog's accessible name, and the list's. It is read by screen readers
* and never drawn, because the palette's shell has no header.
*/
title?: string
}
export interface CommandPaletteEmits {
/**
* Fired when the user picks an item. The palette closes right after, unless
* the handler calls `event.preventDefault()`.
*/
select: [value: CommandPaletteValue, event: CommandPaletteSelectEvent]
}
export interface CommandPaletteSlotProps {
/** The current search text. */
query: string
/** The value of the item the keyboard is on, or `undefined`. */
active: CommandPaletteValue | undefined
/** Whether no item is on screen, hidden by the query or never given. */
empty: boolean
}
export interface CommandPaletteInputProps {
/** Placeholder text for the search field. */
placeholder?: string
}
export interface CommandPaletteGroupProps {
/** Heading above the group's items. Leave it out to group without a heading. */
label?: string
}
export interface CommandPaletteItemProps {
/** The value the palette reports in `select`. */
value: CommandPaletteValue
/**
* Text the client filter matches. It defaults to the item's own rendered
* text, so set it only when the default slot draws more than the label.
* An item that draws no text at all has to set it, or the filter can never
* narrow it away.
*/
label?: string
/** Extra words the client filter matches, on top of the label. */
keywords?: string[]
/** Stop the user picking this item. */
disabled?: boolean
/**
* Element the item renders as. Use `a` with an `href` for a real link, so
* middle-click and modifier-click open a new tab.
*/
as?: string | Component
}
export interface CommandPaletteItemEmits {
/**
* Fired when this item is picked, before the palette's own `select`. Call
* `event.preventDefault()` to keep the palette open.
*/
select: [event: CommandPaletteSelectEvent]
}
export interface CommandPaletteItemSlotProps {
/** Whether the keyboard or the pointer is on this item. */
active: boolean
/** Whether the item cannot be picked. */
disabled: boolean
}
export interface CommandPaletteEmptySlotProps {
/** The current search text. */
query: string
}
export interface CommandPaletteFooterSlotProps {
/** The value of the item the keyboard is on, or `undefined`. */
active: CommandPaletteValue | undefined
}Filter the items against the query on the client. Set it to `false` when a server search already decided what matches (ADR-0009), then refetch on `update:query` yourself.
The dialog's accessible name, and the list's. It is read by screen readers and never drawn, because the palette's shell has no header.
Whether the palette is open.
The search text. Cleared when the palette closes.
| Slot | Payload |
|---|---|
default | CommandPaletteSlotProps The palette's parts. Receives the query, the active value and the empty state. |
The palette's parts. Receives the query, the active value and the empty state.
| Event | Payload |
|---|---|
update:open | [value: boolean] Fired when the open state changes. |
select | [value: AcceptableValue, event: CommandPaletteSelectEvent] Fired when the user picks an item. The palette closes right after, unless the handler calls `event.preventDefault()`. |
update:query | [value: string] Fired when the query changes. |
Fired when the open state changes.
Fired when the user picks an item. The palette closes right after, unless the handler calls `event.preventDefault()`.
Fired when the query changes.
CommandPaletteInput
Show types
import type { AcceptableValue } from 'reka-ui'
import type { Component } from 'vue'
/**
* A value a `CommandPaletteItem` can carry. The palette hands it back
* untouched in `select`, so most apps pass their own command object.
*/
export type CommandPaletteValue = AcceptableValue
/**
* The event `CommandPalette` and `CommandPaletteItem` emit on `select`.
*
* `detail.originalEvent` is the click that picked the item, so a caller can
* read `metaKey`, `ctrlKey`, `shiftKey` and `button`. Call `preventDefault()`
* on the event itself to keep the palette open.
*/
export type CommandPaletteSelectEvent = CustomEvent<{
originalEvent: PointerEvent
value?: CommandPaletteValue
}>
export interface CommandPaletteProps {
/**
* Filter the items against the query on the client. Set it to `false` when a
* server search already decided what matches (ADR-0009), then refetch on
* `update:query` yourself.
*/
filterable?: boolean
/**
* The dialog's accessible name, and the list's. It is read by screen readers
* and never drawn, because the palette's shell has no header.
*/
title?: string
}
export interface CommandPaletteEmits {
/**
* Fired when the user picks an item. The palette closes right after, unless
* the handler calls `event.preventDefault()`.
*/
select: [value: CommandPaletteValue, event: CommandPaletteSelectEvent]
}
export interface CommandPaletteSlotProps {
/** The current search text. */
query: string
/** The value of the item the keyboard is on, or `undefined`. */
active: CommandPaletteValue | undefined
/** Whether no item is on screen, hidden by the query or never given. */
empty: boolean
}
export interface CommandPaletteInputProps {
/** Placeholder text for the search field. */
placeholder?: string
}
export interface CommandPaletteGroupProps {
/** Heading above the group's items. Leave it out to group without a heading. */
label?: string
}
export interface CommandPaletteItemProps {
/** The value the palette reports in `select`. */
value: CommandPaletteValue
/**
* Text the client filter matches. It defaults to the item's own rendered
* text, so set it only when the default slot draws more than the label.
* An item that draws no text at all has to set it, or the filter can never
* narrow it away.
*/
label?: string
/** Extra words the client filter matches, on top of the label. */
keywords?: string[]
/** Stop the user picking this item. */
disabled?: boolean
/**
* Element the item renders as. Use `a` with an `href` for a real link, so
* middle-click and modifier-click open a new tab.
*/
as?: string | Component
}
export interface CommandPaletteItemEmits {
/**
* Fired when this item is picked, before the palette's own `select`. Call
* `event.preventDefault()` to keep the palette open.
*/
select: [event: CommandPaletteSelectEvent]
}
export interface CommandPaletteItemSlotProps {
/** Whether the keyboard or the pointer is on this item. */
active: boolean
/** Whether the item cannot be picked. */
disabled: boolean
}
export interface CommandPaletteEmptySlotProps {
/** The current search text. */
query: string
}
export interface CommandPaletteFooterSlotProps {
/** The value of the item the keyboard is on, or `undefined`. */
active: CommandPaletteValue | undefined
}Placeholder text for the search field.
| Slot | Payload |
|---|---|
prefix | — Replaces the leading search icon. |
suffix | — Trailing content, after the field. |
Replaces the leading search icon.
Trailing content, after the field.
CommandPaletteList
| Slot | Payload |
|---|---|
default | — The palette's groups and items. This element is the listbox itself, and a listbox owns options and groups only, so anything else belongs outside it. |
The palette's groups and items. This element is the listbox itself, and a listbox owns options and groups only, so anything else belongs outside it.
CommandPaletteGroup
Show types
import type { AcceptableValue } from 'reka-ui'
import type { Component } from 'vue'
/**
* A value a `CommandPaletteItem` can carry. The palette hands it back
* untouched in `select`, so most apps pass their own command object.
*/
export type CommandPaletteValue = AcceptableValue
/**
* The event `CommandPalette` and `CommandPaletteItem` emit on `select`.
*
* `detail.originalEvent` is the click that picked the item, so a caller can
* read `metaKey`, `ctrlKey`, `shiftKey` and `button`. Call `preventDefault()`
* on the event itself to keep the palette open.
*/
export type CommandPaletteSelectEvent = CustomEvent<{
originalEvent: PointerEvent
value?: CommandPaletteValue
}>
export interface CommandPaletteProps {
/**
* Filter the items against the query on the client. Set it to `false` when a
* server search already decided what matches (ADR-0009), then refetch on
* `update:query` yourself.
*/
filterable?: boolean
/**
* The dialog's accessible name, and the list's. It is read by screen readers
* and never drawn, because the palette's shell has no header.
*/
title?: string
}
export interface CommandPaletteEmits {
/**
* Fired when the user picks an item. The palette closes right after, unless
* the handler calls `event.preventDefault()`.
*/
select: [value: CommandPaletteValue, event: CommandPaletteSelectEvent]
}
export interface CommandPaletteSlotProps {
/** The current search text. */
query: string
/** The value of the item the keyboard is on, or `undefined`. */
active: CommandPaletteValue | undefined
/** Whether no item is on screen, hidden by the query or never given. */
empty: boolean
}
export interface CommandPaletteInputProps {
/** Placeholder text for the search field. */
placeholder?: string
}
export interface CommandPaletteGroupProps {
/** Heading above the group's items. Leave it out to group without a heading. */
label?: string
}
export interface CommandPaletteItemProps {
/** The value the palette reports in `select`. */
value: CommandPaletteValue
/**
* Text the client filter matches. It defaults to the item's own rendered
* text, so set it only when the default slot draws more than the label.
* An item that draws no text at all has to set it, or the filter can never
* narrow it away.
*/
label?: string
/** Extra words the client filter matches, on top of the label. */
keywords?: string[]
/** Stop the user picking this item. */
disabled?: boolean
/**
* Element the item renders as. Use `a` with an `href` for a real link, so
* middle-click and modifier-click open a new tab.
*/
as?: string | Component
}
export interface CommandPaletteItemEmits {
/**
* Fired when this item is picked, before the palette's own `select`. Call
* `event.preventDefault()` to keep the palette open.
*/
select: [event: CommandPaletteSelectEvent]
}
export interface CommandPaletteItemSlotProps {
/** Whether the keyboard or the pointer is on this item. */
active: boolean
/** Whether the item cannot be picked. */
disabled: boolean
}
export interface CommandPaletteEmptySlotProps {
/** The current search text. */
query: string
}
export interface CommandPaletteFooterSlotProps {
/** The value of the item the keyboard is on, or `undefined`. */
active: CommandPaletteValue | undefined
}Heading above the group's items. Leave it out to group without a heading.
| Slot | Payload |
|---|---|
default | — The group's `CommandPaletteItem`s. |
The group's `CommandPaletteItem`s.
CommandPaletteItem
Show types
import type { AcceptableValue } from 'reka-ui'
import type { Component } from 'vue'
/**
* A value a `CommandPaletteItem` can carry. The palette hands it back
* untouched in `select`, so most apps pass their own command object.
*/
export type CommandPaletteValue = AcceptableValue
/**
* The event `CommandPalette` and `CommandPaletteItem` emit on `select`.
*
* `detail.originalEvent` is the click that picked the item, so a caller can
* read `metaKey`, `ctrlKey`, `shiftKey` and `button`. Call `preventDefault()`
* on the event itself to keep the palette open.
*/
export type CommandPaletteSelectEvent = CustomEvent<{
originalEvent: PointerEvent
value?: CommandPaletteValue
}>
export interface CommandPaletteProps {
/**
* Filter the items against the query on the client. Set it to `false` when a
* server search already decided what matches (ADR-0009), then refetch on
* `update:query` yourself.
*/
filterable?: boolean
/**
* The dialog's accessible name, and the list's. It is read by screen readers
* and never drawn, because the palette's shell has no header.
*/
title?: string
}
export interface CommandPaletteEmits {
/**
* Fired when the user picks an item. The palette closes right after, unless
* the handler calls `event.preventDefault()`.
*/
select: [value: CommandPaletteValue, event: CommandPaletteSelectEvent]
}
export interface CommandPaletteSlotProps {
/** The current search text. */
query: string
/** The value of the item the keyboard is on, or `undefined`. */
active: CommandPaletteValue | undefined
/** Whether no item is on screen, hidden by the query or never given. */
empty: boolean
}
export interface CommandPaletteInputProps {
/** Placeholder text for the search field. */
placeholder?: string
}
export interface CommandPaletteGroupProps {
/** Heading above the group's items. Leave it out to group without a heading. */
label?: string
}
export interface CommandPaletteItemProps {
/** The value the palette reports in `select`. */
value: CommandPaletteValue
/**
* Text the client filter matches. It defaults to the item's own rendered
* text, so set it only when the default slot draws more than the label.
* An item that draws no text at all has to set it, or the filter can never
* narrow it away.
*/
label?: string
/** Extra words the client filter matches, on top of the label. */
keywords?: string[]
/** Stop the user picking this item. */
disabled?: boolean
/**
* Element the item renders as. Use `a` with an `href` for a real link, so
* middle-click and modifier-click open a new tab.
*/
as?: string | Component
}
export interface CommandPaletteItemEmits {
/**
* Fired when this item is picked, before the palette's own `select`. Call
* `event.preventDefault()` to keep the palette open.
*/
select: [event: CommandPaletteSelectEvent]
}
export interface CommandPaletteItemSlotProps {
/** Whether the keyboard or the pointer is on this item. */
active: boolean
/** Whether the item cannot be picked. */
disabled: boolean
}
export interface CommandPaletteEmptySlotProps {
/** The current search text. */
query: string
}
export interface CommandPaletteFooterSlotProps {
/** The value of the item the keyboard is on, or `undefined`. */
active: CommandPaletteValue | undefined
}The value the palette reports in `select`.
Text the client filter matches. It defaults to the item's own rendered text, so set it only when the default slot draws more than the label. An item that draws no text at all has to set it, or the filter can never narrow it away.
Extra words the client filter matches, on top of the label.
Stop the user picking this item.
Element the item renders as. Use `a` with an `href` for a real link, so middle-click and modifier-click open a new tab.
| Slot | Payload |
|---|---|
default | CommandPaletteItemSlotProps The item's label. The client filter matches its text. |
prefix | CommandPaletteItemSlotProps Leading content, before the label. |
suffix | CommandPaletteItemSlotProps Trailing content, pushed to the end of the row. |
The item's label. The client filter matches its text.
Leading content, before the label.
Trailing content, pushed to the end of the row.
| Event | Payload |
|---|---|
select | [event: CommandPaletteSelectEvent] Fired when this item is picked, before the palette's own `select`. Call `event.preventDefault()` to keep the palette open. |
Fired when this item is picked, before the palette's own `select`. Call `event.preventDefault()` to keep the palette open.
CommandPaletteEmpty
| Slot | Payload |
|---|---|
default | CommandPaletteEmptySlotProps The message. Receives the query so it can quote what the user typed. |
The message. Receives the query so it can quote what the user typed.
CommandPaletteFooter
| Slot | Payload |
|---|---|
default | CommandPaletteFooterSlotProps The footer's content. Receives the active value, so a hint can follow it. |
The footer's content. Receives the active value, so a hint can follow it.