Skip to content

bindKey

bindKey(spec, description?, press?, mode?): void

Defined in: keys.ts:236

Bind a keyboard shortcut, for as long as the calling scope lives.

The spec is a KeyboardEvent.key value — "k", "f2", "escape" ("esc"), "space", "arrowdown", a bare "?" — optionally prefixed by mod+ (⌘ on a Mac, Ctrl elsewhere) and/or shift+, in that order: "mod+k", "shift+f2", "mod+shift+b". Case doesn’t matter. A character Shift itself types is written as that character — "?", never "shift+/" — so a combination works on every keyboard layout. No other modifiers are offered: Alt and the ⊞ key belong to the browser and the OS, which also keep some mod combinations for themselves — T, N, W, Q and the digits among them, while K, B, E, / and . are safely yours. Everything Staffa takes a key option is spelled this way, and formatKey turns it back into "⇧⌘K"/"Ctrl+Shift+K".

description is what the shortcut overview (see showKeyHelp) lists the binding as — a rich-text string or draw function; without one the binding stays out of the overview. Omit press to merely describe a key your app handles by other means, so the overview can still tell the user about it.

A handler of the app’s own that ran preventDefault() first always wins, and keystrokes the focused element owns (typing into a field, Enter on a link) are left to it. Otherwise mode says who else can reach the binding:

  • "normal" (the default): works app-wide, but is silenced while a modal dialog from outside it is up. Binding the same combination again shadows the earlier binding until the new scope dies — so a state can take a key over temporarily.
  • "global": keeps working even over a modal.
  • "local": only fires while the keyboard focus is inside the current element — for a shortcut that belongs to one row or panel of many.
  • an Element: like "local", but for that element rather than the current one.

string

Slot

(e) => void

"normal" | "global" | "local" | Element

void

S.bindKey("mod+k", "Search", openSearch);
S.bindKey("mod+z", "Undo"); // describe only: handled by our own listener