# Command palette

A modal search, opened with ⌘K or Ctrl+K from any WerkOS screen, that jumps to a module or a record.

* Kind: component
* Page: https://design.werklist.com/components/command-palette
* Version: 2.1.2

## When to use it

* Reaching a module or a record by name from anywhere.
* Before a letter is typed it lists the modules you can open, so it also serves as a jump list.

## When not to use it

* Narrowing the list on the current page: use that page's search field.
* Commands that change data: actions stay in toolbars.
* In place of the rail and the modules panel.

## Anatomy

* Layer: over the whole window, the panel 12 percent of the window from the top, 16 px from the sides (--layer-dialog)
* Backdrop: dimmed and blurred 8 px. A click on it closes the palette (--overlay)
* Panel: up to 512 px wide, radius 16 px, no border. In dark it adds the glass highlight and a 0.5 px ring, in light the shadow alone (--radius-2xl, --glass-fill-raised, --glass-shadow-raised, --glass-highlight, --glass-ring-raised)
* Field row: 52 px, padding 12 px by 16 px, 16 px search glyph, gap 10 px, text 14 px, 16 px on a touch screen. A 16 px spinner at the end while a search runs (--text-muted)
* Separator: 1 px under the field row, because the list scrolls beneath it (--border-rule)
* List: up to 60 percent of the window high, padding 8 px, with its own scroll
* Row: 40 px, padding 10 px by 12 px, radius 8 px, 18 px glyph in muted ink, gap 12 px, title 14 px (--radius-lg, --text, --text-muted)
* Row with context: 54 px, padding 8 px by 12 px, second line 12 px on 18 px. Each line ends in an ellipsis when it is too long (--text-muted)
* Group title: 13 px on 20 px, weight 500, padding 8 px 12 px 4 px (--text-label)
* Placeholder rows: four rows 34 px high, 4 px apart, each an 18 px square and a 12 px bar at 70, 60, 50 and 40 percent, radius 4 px, pulsing (--glass-fill-hover, --radius-sm)

## States

* Empty query: Lists the modules you can open
* One character: The module list stays
* Searching: From 2 characters, after a 120 ms pause. The newest query wins. Four placeholder rows hold the place until the first results
* Results: Grouped by where they live (--text-label)
* No results: No results for “{query}”, with 40 px of padding (--text-muted)
* Failed: Search did not finish, with a quiet Try again button
* Active row: Soft fill, the same for pointer and keyboard, aria-selected true, kept in view (--glass-fill-hover)
* Enter and exit: Fades in with a 12 px rise from a scale of 0.97, and leaves quicker than it came. With reduced motion it only fades

## Keyboard

* ⌘K (Mac), Ctrl+K (Windows, Linux): Opens or closes the palette
* ArrowDown, ArrowUp: Moves the active row and keeps it in view. Stops at the first and the last row
* Enter: Opens the active row
* Escape: Closes the palette when it is the front layer. Focus returns to where it was
* Tab: Stays inside the dialog

## Accessibility

* Panel: role dialog, aria-modal true, named Search.
* Field: role combobox that controls the list and points to the active option with aria-activedescendant.
* List: role listbox. Each group is named by its title, and each row is an option with aria-selected.
* A polite live region says how many results arrived, or No results.
* Group titles meet 4.5 to 1 on the panel, and muted ink meets 4.5 to 1 on the active row, in both themes.

## Content

* Placeholder: Search everything…
* Rows: the name people know. A second line only when two results could be confused.
* Group titles: the place. A module keeps its proper name with its capitals, such as Global Projects. Any other title is in sentence case: Modules, Files.
* Empty: No results for “{query}”. Failed: Search did not finish. Try again.

## Tokens

* --layer-dialog
* --overlay
* --radius-2xl
* --radius-lg
* --glass-fill-raised
* --glass-shadow-raised
* --glass-fill-hover
* --glass-highlight
* --glass-ring-raised
* --border-rule
* --text
* --text-muted
* --text-label
* --focus-ring
