Don't have TanStack Hotkeys installed yet? See the Installation page for instructions.
The injectHotkey API is the primary way to register keyboard shortcuts in Angular:
import { Component } from '@angular/core'
import { injectHotkey } from '@tanstack/angular-hotkeys'
@Component({
selector: 'app-root',
standalone: true,
template: `<div>Press Cmd+S (Mac) or Ctrl+S (Windows) to save</div>`,
})
export class AppComponent {
constructor() {
injectHotkey('Mod+S', () => {
saveDocument()
})
}
}The Mod modifier automatically resolves to Meta (Command) on macOS and Control on Windows/Linux, so your shortcuts work across platforms without extra logic.
constructor() {
injectHotkey('Mod+S', () => save())
injectHotkey('Mod+Z', () => undo())
injectHotkey('Mod+Shift+Z', () => redo())
injectHotkey('Mod+F', () => openSearch())
injectHotkey('Escape', () => closeDialog())
}import { Component, ElementRef, viewChild } from '@angular/core'
import { injectHotkey } from '@tanstack/angular-hotkeys'
@Component({
standalone: true,
template: `
<div #panel tabindex="0">
<p>Press Escape while focused here to close</p>
</div>
`,
})
export class PanelComponent {
private readonly panel = viewChild<ElementRef<HTMLDivElement>>('panel')
constructor() {
injectHotkey('Escape', () => closePanel(), () => ({
target: this.panel()?.nativeElement ?? null,
}))
}
}import { Component, signal } from '@angular/core'
import { injectHotkey } from '@tanstack/angular-hotkeys'
@Component({ standalone: true, template: `` })
export class ModalComponent {
readonly isOpen = signal(true)
constructor() {
injectHotkey('Escape', () => this.isOpen.set(false), () => ({
enabled: this.isOpen(),
}))
}
}import { injectHotkey } from '@tanstack/angular-hotkeys'
constructor() {
// An array of chords registers a sequence
injectHotkey(['G', 'G'], () => scrollToTop())
injectHotkey(['G', 'Shift+G'], () => scrollToBottom())
}import { Component } from '@angular/core'
import { injectHeldKeys, injectKeyHold } from '@tanstack/angular-hotkeys'
@Component({
standalone: true,
template: `
<div class="status-bar">
@if (isShiftHeld()) {
<span>Shift mode active</span>
}
@if (heldKeys().length > 0) {
<span>Keys: {{ heldKeys().join('+') }}</span>
}
</div>
`,
})
export class StatusBarComponent {
readonly heldKeys = injectHeldKeys()
readonly isShiftHeld = injectKeyHold('Shift')
}import { Component } from '@angular/core'
import { formatForDisplay, injectHotkey } from '@tanstack/angular-hotkeys'
@Component({
standalone: true,
template: `<button>Save <kbd>{{ saveLabel }}</kbd></button>`,
})
export class SaveButtonComponent {
readonly saveLabel = formatForDisplay('Mod+S')
constructor() {
injectHotkey('Mod+S', () => save())
}
}Use provideHotkeys to configure default options for your Angular app:
import { ApplicationConfig } from '@angular/core'
import { provideHotkeys } from '@tanstack/angular-hotkeys'
export const appConfig: ApplicationConfig = {
providers: [
provideHotkeys({
defaultOptions: {
hotkey: { preventDefault: true, timeout: 1500 },
hotkeyRecorder: { onCancel: () => console.log('Recording cancelled') },
},
}),
],
}To list every hotkey in a cheat sheet, including hotkeys whose components haven't mounted, and to let users customize them, declare them once with defineAppHotkeys and provide them with provideHotkeys. See the App Hotkeys Guide.
Install the optional devtools packages to inspect registrations, held keys, and trigger counts:
npm install @tanstack/angular-devtools @tanstack/angular-hotkeys-devtoolsThe Angular devtools integration requires Angular 21 or newer. Follow the devtools setup guide to add the dock to your application.