Command
The ⌘K menu. Type to filter, arrow keys to move, Enter to run. Filtering happens in the
PetalCommand
hook so keystrokes never wait on the server, and every item is a real link or button - so navigate,
patch
and any phx-*
binding work exactly as they do everywhere else in LiveView. The markup follows the WAI-ARIA
combobox pattern, so it's keyboard and screen-reader friendly out of the box.
Inline palette
The inline shell is command/1
- a palette panel you can drop into a page, sidebar or picker. Start typing to filter the
items; the highlight moves with the arrow keys and Enter runs the selection.
The ⌘K dialog
command_dialog/1
is the same palette in a native <dialog>, so the top layer, focus trap,
backdrop and Escape all come from the browser. Open it with the bound key
(⌘K
/ Ctrl+K
by default) or from any element with open_command/1. Selecting an item closes the dialog automatically.
(This site already binds ⌘K
to its own search, so the demo below opens from
the button - pass shortcut=""
to skip the global key when it's already taken.)
Filtering and keywords
The hook matches the visible label plus any keywords
you add, so "schedule" can find Calendar
even though the word never appears on screen. Items are hidden, never reordered - the server
owns DOM order, which keeps everything safe under LiveView patches. Pass loop
to wrap the arrow keys from the last item back to the first.
Properties
command/1 and command_dialog/1 (the two shells):
# command/1 - the inline palette
attr :id, :string, required: true, doc: "unique id; the PetalCommand hook mounts here"
attr :loop, :boolean, default: false, doc: "arrow keys wrap from the last item to the first"
attr :class, :any, default: nil
attr :rest, :global
slot :inner_block, required: true
# command_dialog/1 - the palette in a native <dialog>
attr :id, :string, required: true
attr :shortcut, :string, default: "k", doc: "key bound with Cmd/Ctrl to toggle; nil disables it"
attr :loop, :boolean, default: false
attr :reset_on_close, :boolean, default: true, doc: "clear the query when the dialog closes"
attr :class, :any, default: nil
attr :rest, :global
slot :inner_block, required: true
The pieces inside: command_input/1, command_list/1
(with an accessible label), command_empty/1,
command_group/1
(heading), command_separator/1, command_shortcut/1, and command_item/1:
# command_item/1
attr :value, :string, doc: "used for filtering; defaults to the item's text"
attr :keywords, :list, default: [], doc: "extra search aliases for this item"
attr :disabled, :boolean, default: false
attr :navigate, :string, default: nil, doc: "live_redirect target - renders the item as a link"
attr :patch, :string, default: nil, doc: "live_patch target - renders the item as a link"
attr :rest, :global, doc: "e.g. phx-click, data-keep-open"
slot :inner_block, required: true