{#- chirp-ui: Command Palette component Cmd+K search overlay using native . Results load via htmx into the results container; render them with `command_palette_item` so the input gets arrow-key result navigation. The input is a `role="combobox"` over the `role="listbox"` results: ArrowDown/ ArrowUp rove the `role="option"` items via `aria-activedescendant` (the active item carries `aria-selected="true"`), Enter activates the active item, and each fresh htmx result set auto-highlights its first item. Requires Alpine.js; arrow-nav only engages over `command_palette_item` (role=option) results — legacy raw-HTML results stay Tab-navigable. Usage: from "chirpui/command_palette.html" import ( command_palette, command_palette_trigger, command_palette_item ) command_palette_trigger() call command_palette(search_url="/search") {# optional initial/recent results #} end {# /search returns the results fragment: #} command_palette_item("cmd-new", "New document", href="/docs/new", hint="N") -#} {% def command_palette(id="command-palette", search_url="/search", placeholder="Search...") %}
{% slot %}
{% end %} {#- One command-palette result. role="option" with a stable id so the combobox input can track it via aria-activedescendant. Plain (no Alpine directives) so htmx can swap result sets cleanly — the chirpuiCommandPalette factory sets aria-selected + the --active class imperatively as focus roves. Renders an when `href` is set, otherwise a {% end %} {% end %} {% def command_palette_trigger(target="command-palette", label="Search", placeholder=none, shortcut="⌘K", icon=none, aria_label=none, density="md", cls="") %} {% set density = density | validate_variant(("sm","md"), "md") %} {% set visible_label = placeholder if placeholder is not none else label %} {% set control_label = aria_label if aria_label is not none else label %} {% end %}