Command palette — accessibility

Keyboard

  • ⌘K / Ctrl+K opens the palette from anywhere; Esc closes it.
  • ↑ / ↓ move through a flat index across all Item lists in the left column — sections do not trap the cursor, so one hold of the arrow key crosses from Lidé into Firmy.
  • ↵ opens the row under the cursor. ⌘↵ hands the query to the assistant (the same path as clicking the footer).
  • The cursor sits on the first row from the moment the palette opens, so ↵ always does something.
  • A prefix character (@ # > ?) is consumed into the .gsp-pre token; Backspace on an empty field removes the token and returns to the full scope.
  • Locked rows are not focusable and carry no click — they are found and marked, never opened.
  • On mobile the detail is a second step: opening a row replaces the list, and .gsp-back returns to it.

ARIA

  • The shell is role="dialog" with aria-modal="true" and aria-label="Hledat".
  • The input is role="combobox" with aria-expanded, aria-haspopup="listbox" and aria-activedescendant pointing at the active row.
  • Each section's list is role="listbox" with ariaLabel set to the section title; rows are role="option".
  • The active row is announced through aria-activedescendant — focus itself never leaves the input, so typing continues to work while the cursor walks the list.
  • The .acrm-kbd shortcut chips are aria-hidden: they are a visual hint, and the accessible name is carried by the row and by the button label.

Focus

  • Focus enters the input on open and stays there for the whole session of the overlay.
  • On close, focus returns to what invoked the palette.
  • The footer is a real <button> spanning the full width of the footer row, so it is reachable by Tab as well as by ⌘↵.

Contrast

  • Row text --ink-900 on --surface-100; secondary and tertiary slots step down through --fg-secondary and --fg-muted, all on the same 13px type — the hierarchy is carried by colour, never by size or weight.
  • The status strip uses --warning-ink on --warning-subtle; a failed section label uses --critical-ink.
  • The match highlight is --accent-ink on --accent-tint, the same pair the meeting transcript search uses.
  • The active row is --selected, which is a background change only — the row keeps its text colours.

Known limits

  • The cursor index is flat across lists, so a screen reader hears section boundaries only through the listbox labels, not through a position announcement.
  • The status strip is not a live region: it is rendered with the results rather than announced when the engine state changes.
  • The masked sub-label of a locked row is the literal ***, written by the client — the server never sends the hidden values, so there is nothing more descriptive to announce.

Source: docs/command-palette/command-palette.a11y.md · GitLab