Overlays
Command palette
Search-driven actions behind Cmd+K.
A ⌘K dialog: a modal combobox over a listbox of actions, on the shared overlay
runtime. The component owns opening, the focus trap, keyboard traversal, and
aria-activedescendant; it never filters its own children
— it renders exactly the items you hand it and reports the query upward, so search
can come from a database, an index, or memory.
Searchable actions
Press ⌘J (Ctrl+J on Windows/Linux; ⌘K is the docs search) or use the button. Type to filter, ↑/↓ to move, Enter to choose, Esc to close. Filtering happens in the LiveView — the palette itself renders whatever it is given.
Nothing chosen yet — open the palette and press Enter on a row.
# LiveView - the palette does no filtering, so you do
def handle_event("command_search", %{"query" => query}, socket) do
{:noreply, assign(socket, query: query, groups: command_matches(query))}
end
def handle_event("command_select", %{"value" => value}, socket) do
{:noreply, assign(socket, :selection, value)}
end
<.button phx-click={LanternUI.open_dialog("cmd-demo")}>
Search... <.command_shortcut>Cmd+K</.command_shortcut>
</.button>
<.command id="cmd-demo" on_search="command_search" on_select="command_select">
<%= for {{group, items}, index} <- Enum.with_index(@groups) do %>
<.command_separator :if={index > 0} />
<.command_group label={group}>
<.command_item :for={cmd <- items} value={cmd.value} disabled={cmd.disabled}>
<:icon><.icon name={cmd.icon} /></:icon>
{cmd.label}
<:description>{cmd.description}</:description>
<:shortcut>{cmd.shortcut}</:shortcut>
</.command_item>
</.command_group>
<% end %>
<.command_empty :if={@groups == []}>No commands match "{@query}".</.command_empty>
<:footer>Up/Down to navigate - Enter to select - Esc to close</:footer>
</.command>
API reference
Props and slots, introspected from the component.
command/1| Prop | Type | Default | Description |
|---|---|---|---|
backdrop_class |
any |
nil |
Extra classes on the dimmed backdrop. |
class |
any |
nil |
Extra classes on the dialog panel. |
close_on_esc |
boolean |
true |
Close when Escape is pressed. |
close_on_outside_click |
boolean |
true |
Close when the backdrop is clicked. |
close_on_select |
boolean |
true |
Close the palette after an item is chosen. |
container_class |
any |
nil |
Extra classes on the overlay root. |
debounce |
integer |
200 |
Search debounce in milliseconds. |
hotkey |
string |
"k" |
Key that opens the palette with Meta/Ctrl. `nil` disables the global hotkey. |
id* |
string |
— |
Stable DOM id used by open_dialog/close_dialog. |
label |
string |
"Command palette" |
Accessible name for the dialog and the results listbox. |
list_class |
any |
nil |
Extra classes on the scrollable results list. |
loading |
boolean |
false |
Show the loading row above the results. |
on_search |
string |
"command_search" |
LiveView event pushed with `%{"query" => query}`. `nil` disables searching. |
on_select |
string |
"command_select" |
LiveView event pushed with `%{"value" => value}` when an item without its own `phx-click` is activated. `nil` disables it. |
open |
boolean |
false |
Render already open (server-driven palettes). |
placeholder |
string |
"Type a command or search…" |
Search input placeholder. |
search_on_open |
boolean |
true |
Push `on_search` with the current query when the palette opens. |
target |
any |
nil |
LiveComponent to send `on_search`/`on_select` to, 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. |
| Slots | |||
:footer |
Sticky footer under the results (hints, counts). | ||
:inner_block* |
Results: groups, items, separators, empty state. | ||
command_group/1| Prop | Type | Default | Description |
|---|---|---|---|
class |
any |
nil |
Extra classes merged onto the group. |
id |
any |
nil |
Element id; auto-generated when omitted. |
label |
string |
nil |
Section heading rendered above the items. |
| Slots | |||
:inner_block* |
Items belonging to this group. | ||
command_item/1| Prop | Type | Default | Description |
|---|---|---|---|
class |
any |
nil |
Extra classes merged onto the row. |
disabled |
boolean |
false |
Render the row unselectable. |
id |
any |
nil |
Element id; auto-generated when omitted. |
value |
any |
nil |
Value sent as `%{"value" => value}` when the item is selected. |
| Slots | |||
:description |
Secondary line under the label. | ||
:icon |
Leading icon or avatar. | ||
:inner_block* |
Item label. | ||
:shortcut |
Trailing keyboard hint or badge. | ||
command_empty/1| Prop | Type | Default | Description |
|---|---|---|---|
class |
any |
nil |
Extra classes merged onto the empty state. |
| Slots | |||
:inner_block* |
Empty-state copy. | ||
command_separator/1| Prop | Type | Default | Description |
|---|---|---|---|
class |
any |
nil |
Extra classes merged onto the separator. |
command_shortcut/1| Prop | Type | Default | Description |
|---|---|---|---|
class |
any |
nil |
Extra classes merged onto the shortcut hint. |
| Slots | |||
:inner_block* |
Keyboard hint text, e.g. `⌘K`. | ||