A command palette — the ⌘K menu. Type to filter, arrow keys to move,
Enter to run. Items are real links and buttons, so navigate, patch
and any phx-* binding work exactly as they do everywhere else in
LiveView.
Filtering happens client-side in the PetalCommand hook (zero
dependencies), so keystrokes never wait on the server. Items are hidden,
never reordered — the server owns DOM order, which keeps the component
safe under LiveView patches.
Two shells:
command/1— an inline palette panel (for docs pages, sidebars, pickers).command_dialog/1— the palette in a native<dialog>, opened with ⌘K / Ctrl+K (configurable) orJS.dispatch("pc:command-open"). The native element gives the top layer, focus trap, backdrop and Escape for free.
The markup follows the WAI-ARIA combobox pattern: the input carries
role="combobox" and aria-activedescendant, the list is a listbox,
items are options. Keyboard focus never leaves the input; selection is
a virtual highlight.
Summary
Functions
The inline command palette.
The command palette in a native <dialog> — the classic ⌘K experience.
Shown only when the query matches nothing.
Groups related items. Hides itself when every item inside is filtered out.
The search field. Keyboard focus lives here; the list highlight is virtual.
One entry in the palette. A link when navigate/patch/href is set,
a button otherwise. value (plus keywords) is what typing matches;
it defaults to the item's visible text.
Scrollable container for groups and items.
A hairline between groups. Hidden automatically while a query is active.
A right-aligned keyboard hint inside an item.
Returns a JS command that opens the command dialog with the given id.
Compose it onto any trigger: phx-click={open_command("cmdk")}.
Functions
The inline command palette.
<.command id="file-menu">
<.command_input placeholder="Type a command or search..." />
<.command_list>
<.command_empty>No results found.</.command_empty>
<.command_group heading="Suggestions">
<.command_item navigate={~p"/calendar"}>
<.icon name="hero-calendar" /> Calendar
</.command_item>
<.command_item phx-click="open_emoji">
<.icon name="hero-face-smile" /> Search emoji
<.command_shortcut>⌘E</.command_shortcut>
</.command_item>
</.command_group>
</.command_list>
</.command>Attributes
id(:string) (required) - unique id; the PetalCommand hook mounts here.loop(:boolean) - arrow keys wrap from the last item to the first and back. Defaults tofalse.class(:any) - extra classes for the palette panel. Defaults tonil.- Global attributes are accepted.
Slots
inner_block(required)
The command palette in a native <dialog> — the classic ⌘K experience.
<.command_dialog id="cmdk">
<.command_input placeholder="Type a command or search..." />
<.command_list>
<.command_empty>No results found.</.command_empty>
...
</.command_list>
</.command_dialog>Open it from any element:
<.button phx-click={PetalComponents.Command.open_command("cmdk")}>
Search <.command_shortcut>⌘K</.command_shortcut>
</.button>The dialog closes on Escape, backdrop click, or after an item runs
(add data-keep-open to an item to opt out).
Attributes
id(:string) (required) - unique id for the dialog; open it with ⌘K or open_command/1.shortcut(:string) - the key bound with Cmd (mac) / Ctrl to toggle the dialog. Set to nil to disable the global binding. Defaults to"k".loop(:boolean) - arrow keys wrap around the list. Defaults tofalse.reset_on_close(:boolean) - clear the query (and restore all items) when the dialog closes. Defaults totrue.class(:any) - extra classes for the palette panel inside the dialog. Defaults tonil.- Global attributes are accepted.
Slots
inner_block(required)
Shown only when the query matches nothing.
Attributes
class(:any) - Defaults tonil.- Global attributes are accepted.
Slots
inner_block(required)
Groups related items. Hides itself when every item inside is filtered out.
Attributes
heading(:string) - group heading, rendered above the items. Defaults tonil.class(:any) - Defaults tonil.- Global attributes are accepted.
Slots
inner_block(required)
The search field. Keyboard focus lives here; the list highlight is virtual.
Attributes
placeholder(:string) - Defaults to"Type a command or search...".autofocus(:boolean) - focus the input on mount (dialogs focus it on open regardless). Defaults tofalse.class(:any) - Defaults tonil.- Global attributes are accepted.
One entry in the palette. A link when navigate/patch/href is set,
a button otherwise. value (plus keywords) is what typing matches;
it defaults to the item's visible text.
Attributes
value(:string) - the text the filter matches against. Defaults to the item's visible text. Defaults tonil.keywords(:list) - extra search aliases for this item. Defaults to[].disabled(:boolean) - Defaults tofalse.navigate(:string) - live_redirect target - renders the item as a link. Defaults tonil.patch(:string) - live_patch target - renders the item as a link. Defaults tonil.href(:string) - plain link target - renders the item as a link. Defaults tonil.class(:any) - Defaults tonil.- Global attributes are accepted. phx-click and friends work here - Enter clicks the highlighted item. Supports all globals plus:
["target", "rel", "method", "download"].
Slots
inner_block(required)
Scrollable container for groups and items.
Attributes
label(:string) - accessible name for the listbox. Defaults to"Commands".class(:any) - Defaults tonil.- Global attributes are accepted.
Slots
inner_block(required)
A hairline between groups. Hidden automatically while a query is active.
Attributes
class(:any) - Defaults tonil.- Global attributes are accepted.
A right-aligned keyboard hint inside an item.
Attributes
class(:any) - Defaults tonil.- Global attributes are accepted.
Slots
inner_block(required)
Returns a JS command that opens the command dialog with the given id.
Compose it onto any trigger: phx-click={open_command("cmdk")}.