Command palette (⌘K dialog) — a modal combobox over a listbox of actions.
There is no Fluxon equivalent; the structure mirrors shadcn's Base UI
Command (input → list → groups → items → empty), translated onto Lantern's
dialog runtime and tokens.
Filtering is the consumer's job
The component never filters its own children. It renders exactly the items it is handed and reports the query upward, so a LiveView can answer from a database, a search index, or memory:
<.command id="cmd-k" on_search="command_search" on_select="command_select">
<.command_group label="Tickets">
<.command_item :for={t <- @results} value={t.id}>
{t.title}
<:shortcut>{t.number}</:shortcut>
</.command_item>
</.command_group>
<.command_empty :if={@results == []}>No matches for "{@query}"</.command_empty>
</.command>
def handle_event("command_search", %{"query" => q}, socket), do: ...
def handle_event("command_select", %{"value" => v}, socket), do: ...Events, and why they are not phx- attributes
The LanternCommand hook pushes on_search / on_select itself. Nothing in
this component carries a phx-change, phx-submit, or a <form> element, so
mounting the palette in a global app shell cannot make a host app's own
element("form") / form[phx-change=...] test selectors ambiguous. Event
names default to the command_* namespace for the same reason.
Payloads:
on_search→%{"query" => query}(debounced bydebounce, in ms)on_select→%{"value" => value}— pushed only for items that do not carry their ownphx-click, so per-item bindings are never double-fired.
Opening and closing
Shares the dialog contract with LanternUI.Components.Modal:
<.button phx-click={LanternUI.open_dialog("cmd-k")}>Search…</.button>
{:noreply, LanternUI.open_dialog(socket, "cmd-k")}plus the built-in ⌘K / Ctrl+K hotkey (hotkey="k", set hotkey={nil} to
disable). Focus is trapped while open and restored to the previously focused
element on close. Escape and a backdrop click close by default.
Keyboard
↑/↓ move the highlight, Home/End jump, Enter activates the
highlighted item, Escape closes. Focus stays in the input; the active item
is published with aria-activedescendant (this is a combobox, not the roving
DOM focus used by menu/select).
Supporting parts
Use command_separator/1 between groups or related results. Use
command_shortcut/1 for a standalone keyboard hint; an item's :shortcut
slot is the usual choice for a hint attached to one item. command_group/1,
command_item/1, and command_empty/1 cover grouped results, selectable
rows, and the empty state.
<.command_separator />
<.command_shortcut>Ctrl+K</.command_shortcut>
Summary
Functions
Attributes
id(:string) (required) - Stable DOM id used by open_dialog/close_dialog.open(:boolean) - Render already open (server-driven palettes). Defaults tofalse.label(:string) - Accessible name for the dialog and the results listbox. Defaults to"Command palette".placeholder(:string) - Search input placeholder. Defaults to"Type a command or search…".target(:any) - LiveComponent to sendon_search/on_selectto, as@myself.Required when the palette is rendered from INSIDE a LiveComponent: without it the hook pushes to the parent LiveView, which then has to define handlers it has no business owning. A global palette in an app shell is almost always a LiveComponent, so this is the normal case rather than an edge one.
Defaults to
nil.on_search(:string) - LiveView event pushed with%{"query" => query}.nildisables searching. Defaults to"command_search".on_select(:string) - LiveView event pushed with%{"value" => value}when an item without its ownphx-clickis activated.nildisables it. Defaults to"command_select".debounce(:integer) - Search debounce in milliseconds. Defaults to200.hotkey(:string) - Key that opens the palette with Meta/Ctrl.nildisables the global hotkey. Defaults to"k".loading(:boolean) - Show the loading row above the results. Defaults tofalse.search_on_open(:boolean) - Pushon_searchwith the current query when the palette opens. Defaults totrue.close_on_esc(:boolean) - Close when Escape is pressed. Defaults totrue.close_on_outside_click(:boolean) - Close when the backdrop is clicked. Defaults totrue.close_on_select(:boolean) - Close the palette after an item is chosen. Defaults totrue.class(:any) - Extra classes on the dialog panel. Defaults tonil.container_class(:any) - Extra classes on the overlay root. Defaults tonil.backdrop_class(:any) - Extra classes on the dimmed backdrop. Defaults tonil.list_class(:any) - Extra classes on the scrollable results list. Defaults tonil.Global attributes are accepted. Arbitrary HTML/
phx-*attributes passed through to the overlay root.
Slots
inner_block(required) - Results: groups, items, separators, empty state.footer- Sticky footer under the results (hints, counts).
Attributes
class(:any) - Extra classes merged onto the empty state. Defaults tonil.- Global attributes are accepted. Arbitrary HTML/
phx-*attributes passed through.
Slots
inner_block(required) - Empty-state copy.
Attributes
id(:any) - Element id; auto-generated when omitted. Defaults tonil.label(:string) - Section heading rendered above the items. Defaults tonil.class(:any) - Extra classes merged onto the group. Defaults tonil.- Global attributes are accepted. Arbitrary HTML/
phx-*attributes passed through.
Slots
inner_block(required) - Items belonging to this group.
Attributes
id(:any) - Element id; auto-generated when omitted. Defaults tonil.value(:any) - Value sent as%{"value" => value}when the item is selected. Defaults tonil.disabled(:boolean) - Render the row unselectable. Defaults tofalse.class(:any) - Extra classes merged onto the row. Defaults tonil.- Global attributes are accepted. Arbitrary HTML/
phx-*attributes. An item with its ownphx-clickdoes not also push the palette'son_selectevent. Supports all globals plus:["phx-click", "phx-target", "phx-value-id"].
Slots
icon- Leading icon or avatar.description- Secondary line under the label.shortcut- Trailing keyboard hint or badge.inner_block(required) - Item label.
Attributes
class(:any) - Extra classes merged onto the separator. Defaults tonil.- Global attributes are accepted. Arbitrary HTML/
phx-*attributes passed through.
Attributes
class(:any) - Extra classes merged onto the shortcut hint. Defaults tonil.- Global attributes are accepted. Arbitrary HTML/
phx-*attributes passed through.
Slots
inner_block(required) - Keyboard hint text, e.g.⌘K.