## command (`poetry_command`)

A command palette for fast, keyboard-driven search and actions.

Class: Poetry::Ui::Command::Component - BEM block `poetry-ui-command`.
REQUIRED - one of id: / aria-label: / aria-labelledby: / aria: (the input's accessible name); a call satisfying none raises.
- `disabled:` (boolean) - default false - Disables the filter input.
- `filter:` (boolean) - default true - Client-side filtering; false leaves the list server-driven.
- `id:` (string) - The base DOM id; the input, list, and item ids derive from it.
- `list_label:` (string) - default "dynamic" - The listbox's accessible name.
- `loop:` (boolean) - default false - Wraps arrow-key highlight movement past either end of the list.
- `placeholder:` (string) - The filter input's placeholder text.
- `value:` (string) - Seats the initial highlight on the item with this value.
Slots: empty (Custom zero-results content (defaults to t('poetry.command.empty')).), loading (Custom pending content (a spinner); the HOST toggles visibility (Turbo frame events) - Command renders the part, never sets it.), items (The item UNION: item | group (heading + items) | separator - one ordered collection (interleaving preserved; items and groups are part COMPONENTS so id assignment follows render/DOM order).; many; types item|group|separator - one with_<type> setter each, options as keywords).
- PART `command` - Root of the palette - the input row over the listbox, carrying the engine controller
- PART `command-input-wrapper` - The input row - search icon + filter input above the list
- PART `command-search-icon` - Decorative search glyph beside the input
- PART `command-input` - The role=combobox filter input - real focus stays pinned here for the whole session; the highlight rides aria-activedescendant
- PART `command-list` - The role=listbox holding empty/loading/items - the input's aria-controls target
- PART `command-empty` - Zero-matches message - rendered hidden; the controller unhides it when the filter pass leaves no visible items
- PART `command-loading` - Pending affordance (role=status) - rendered hidden; the HOST toggles it (Turbo frame events), Command never does
- PART `command-group` - role=group labelled by its heading - hidden by the controller when every member item is filtered out | states: data-always-render (always_render: is set - the group survives every filter pass)
- PART `command-group-heading` - The group heading - styled, no ARIA role (the group points at it via aria-labelledby)
- PART `command-item` - One role=option action row - highlight, filtering, and disablement ride here (never aria-selected in a bare Command) | states: data-value (always - the item's unique value (its server-stable id follows registration order)); data-highlighted (the item holds the highlight (bare; the controller twin-writes it with the input's aria-activedescendant)); data-disabled (disabled: is set (aria-disabled rides along)); data-keywords (keywords: given - extra filter terms beyond the label); data-always-render (always_render: is set - the item survives every filter pass); data-hidden (the filter scored the item zero (the controller pairs it with hidden; never rendered server-side))
- PART `command-item-text` - The item's label span - the filter/typematch text source (shortcuts and icons excluded)
- PART `command-shortcut` - Presentational keyboard hint - excluded from the filter text; Command never binds the hinted key
- PART `command-separator` - Decorative divider (aria-hidden) - hidden by the controller whenever the query is non-empty
- PART `command-status` - The sr-only polite result-count live region - the controller writes the debounced count from the localized templates | states: data-zero (always - the localized zero-results template); data-one (always - the localized one-result template); data-other (always - the localized many-results template (a literal count placeholder the controller interpolates))
- WIRING root: `poetry--core--command` registers; values filter, loop
- WIRING input: `poetry--core--command` actions filterInput on input, keydown on keydown
- WIRING item: `poetry--core--command` actions activate on click, pointerHighlight on pointermove
- RULE: Use poetry_command - never hand-roll a filterable listbox with an input + a list and ad-hoc JS.
- RULE: Command items DO things; they carry no form value. Picking a value for a form is Combobox (which wraps this) - never bind a hidden input to a bare Command.
- RULE: Every item needs a unique value: (ArgumentError) and gets a server id - never strip item ids (aria-activedescendant depends on them).
- RULE: Never put tabindex or focus on options; never write aria-selected in a bare Command - highlight is data-highlighted + activedescendant only.
- RULE: Filtering is hide-only: never reorder, remove, or re-append items to 'sort' results - DOM order is the contract.
- RULE: The poetry:command:select event is the ONLY activation surface - act in a listener (or item data-action); don't patch the controller to navigate.
- RULE: Long/async data: filter: false + a Turbo frame (the recipe) - don't render 5,000 items and hope.
- RULE: Icon-rich labels: set filter_value:/keywords: rather than stuffing hidden text into items.
