DevactionUI.Autocomplete (devaction_ui v0.2.3)

Copy Markdown View Source

Suggestions while you type, in groups (lessons, pull requests, tasks), with the part that matched in bold and an optional last row that asks the AI. The server owns the search: the field sends event (debounced by debounce ms) with the text, and the caller answers with groups; this component draws the field and the list and moves the active row with ↑ ↓, opens it with Enter and runs the AI row with ⌘ + Enter (or Ctrl + Enter). Esc closes the list, typing opens it again. The list also closes when the focus leaves the whole component, a moment after, so the click that chose a row still lands.

A group is %{label: "Lessons", items: [%{id: ..., label: ..., to: path, hint: "30", tone: :warn}]}; each group is a role="group" named by its label. A row goes where to (a LiveView navigation), patch or href says (or sends event with its id); hint is a small mono badge, tone colors it, and hint_style: :plain draws it as bare mono text in the tone, with no background (the number of a pull request or an issue: #142). The AI row sends ask_event with the typed text in the q parameter (phx-value-q). highlight/2 splits a label around the query, ignoring case and accents, for the bold part.

While the server searches, loading shows loading_label (with the loading_icon slot, if any) instead of the "nothing found" text, keeps the rows it has, and sets aria-busy on the list. What a query that finds nothing says is empty, or the empty_state slot when it needs more than text (a link to create the thing); the slot gets the query.

The field tells assistive technology the list is open only when there is a row in it: not for a query that found nothing and has no AI row. Icons are slots (search_icon, with a ⌕ when there is none) and the key caps are DevactionUI.Kbd: ask_kbd is the key of the AI row, written by the caller (⌘↵ on a Mac, Ctrl ↵ elsewhere).

Summary

Functions

Splits label around the first place query appears, ignoring case and accents: highlight("Ecto.Multi", "ecto") is [match: "Ecto", text: ".Multi"]. No match, or a blank query, is the whole label as text.

One row of the list, for DevactionUI.Autocomplete and DevactionUI.CommandPalette: a link when the item has to (a LiveView navigation), patch or href, and a button that sends event with the item's id (as id) when it has event. It is a role="option" the hook can move over.

Functions

autocomplete(assigns)

@spec autocomplete(map()) :: Phoenix.LiveView.Rendered.t()

Attributes

  • id (:string) (required)
  • name (:string) - Defaults to "q".
  • value (:string) - Defaults to "".
  • label (:string) (required) - what is being searched, for assistive technology.
  • placeholder (:string) - Defaults to nil.
  • event (:string) (required) - the event the field sends with the text, debounced.
  • debounce (:integer) - milliseconds the field waits before sending. Defaults to 150.
  • groups (:list) - %{label, items: [%{id, label, to | patch | href, hint, tone}]}. Defaults to [].

  • empty (:string) (required) - shown when a query finds nothing.
  • loading (:boolean) - the server is searching: shows loading_label and marks the list busy. Defaults to false.
  • loading_label (:string) - what the list says while loading. Defaults to nil.
  • ask_label (:string) - the text of the AI row, e.g. Ask the AI about "ecto"; no row when nil. Defaults to nil.
  • ask_event (:string) - the event the AI row sends with the text, as q. Defaults to nil.
  • ask_kbd (:string) - the key of the AI row, as a key cap: ⌘↵; none when nil. Defaults to nil.
  • class (:any) - Defaults to nil.
  • Global attributes are accepted.

Slots

  • search_icon - the magnifier in the field.
  • loading_icon - turning icon before loading_label.
  • empty_state - replaces the empty text; gets the query.

highlight(label, query)

@spec highlight(String.t(), String.t()) :: [{:text | :match, String.t()}]

Splits label around the first place query appears, ignoring case and accents: highlight("Ecto.Multi", "ecto") is [match: "Ecto", text: ".Multi"]. No match, or a blank query, is the whole label as text.

option(assigns)

@spec option(map()) :: Phoenix.LiveView.Rendered.t()

One row of the list, for DevactionUI.Autocomplete and DevactionUI.CommandPalette: a link when the item has to (a LiveView navigation), patch or href, and a button that sends event with the item's id (as id) when it has event. It is a role="option" the hook can move over.

Attributes

  • id (:string) (required)
  • item (:map) (required) - %{to | patch | href} goes there; %{event} sends it with the item's id.

  • class (:any) - Defaults to nil.
  • Global attributes are accepted.

Slots

  • inner_block (required)