Keyboard

Bind shortcuts, show them as keycaps, and see which keys each component handles.

Bind a shortcut

Global by default, or scoped to the host; mod is ⌘ on macOS and Ctrl elsewhere.

Focus me, then pressEsc— caught 0×
<!-- Global: fires wherever focus is. -->
<div [wrHotkey]="'mod+k'" (wrHotkeyMatch)="palette.open()">…</div>

<!-- Scoped: only while focus is inside the host. -->
<div [wrHotkey]="'escape'" [scoped]="true" (wrHotkeyMatch)="close()">…</div>
import { WrHotkey } from 'ngwr/hotkey';

private readonly hotkey = inject(WrHotkey);

constructor() {
  const handle = this.hotkey.bind('mod+k', () => this.palette.open());
  inject(DestroyRef).onDestroy(() => handle.unbind());
}
NameDescriptionTypeDefault
wrHotkeyThe chord, such as mod+k.WrHotkeySpec—
scopedListen only while focus is inside the host.booleanfalse
allowInInputAlso fire while an input, textarea or contenteditable has focus.booleanfalse
preventDefaultStop the browser acting on the chord too.booleantrue
(wrHotkeyMatch)Emits the KeyboardEvent on a match.KeyboardEvent—

Show the keys

<wr-kbd> draws one keycap per key.

⌘KCtrlK
<wr-kbd>⌘</wr-kbd>
<wr-kbd>K</wr-kbd>
<wr-kbd size="sm">Ctrl</wr-kbd>
<wr-kbd size="sm">K</wr-kbd>

Handle keys yourself

Helpers from ngwr/utils for your own keydown handlers.

import { KEYS, hasModifier, isComposing, isPrintableKey } from 'ngwr/utils';

protected onKeydown(event: KeyboardEvent): void {
  if (isComposing(event)) return;
  if (event.key === KEYS.ESCAPE) return this.close();

  // Before hasModifier, which counts Shift and would drop capitals.
  if (isPrintableKey(event)) {
    this.query.update(q => q + event.key);
    return;
  }

  if (hasModifier(event)) return; // leave the browser's own shortcuts alone
}
HelperUse
KEYSTyped KeyboardEvent.key values.
isComposingAn input method is still converting.
isPrintableKeyThe key types a character.
hasModifierCtrl, Cmd, Alt or Shift is held.

What the components handle

Built in, nothing to configure.

  • A composite widget is one tab stop; the arrows move inside it.
  • Left and right arrows swap under dir="rtl"; Home and End do not.
ComponentKeys
Dialog, drawer
Esccloses and returns focus, unless closeOnEscape: false
Tabcycles inside; focus cannot leave
Select
EnterSpace↓↑open the panel
↑↓HomeEndmove through the options
Enterselects (Space too, when there is no search field)
EscTabclose without selecting
Backspaceremoves the last chip, or clears an empty clearable search
Dropdown, context menu
EnterSpace↓↑open and focus the first item
↑↓HomeEndmove focus
→←open / close a context-menu submenu
Esccloses one level and returns focus
Tabs
←→previous / next tab, wrapping
HomeEndfirst / last tab
EnterSpaceactivate, in router mode (wrTabsRouting)
Tree
↑↓previous / next visible row
→expands, or steps into the first child
←collapses, or jumps to the parent
HomeEndfirst / last visible row
EnterSpaceselect; hold Ctrl / ⌘ to add
Pagination
Tabmoves between cells; the arrows do nothing
EnterSpacego to that page
Table
Tabwalks the sort, filter, selection and expand controls
↑↓PgUpPgDnscroll a virtualScroll body

Calendar, event calendar, date picker, image cropper and editor list their keys on their own pages.

See also