Skip to content

Ember Example: UseHotkey

import Component from '@glimmer/component'
import { tracked } from '@glimmer/tracking'

import { on } from '@ember/modifier'

import { formatForDisplay, useHotkey, onHotkey } from '@tanstack/ember-hotkeys'
import type {
  Hotkey,
  RegisterableHotkey,
  HotkeyCallback,
} from '@tanstack/ember-hotkeys'
import { modifier } from 'ember-modifier'

const autofocus = modifier((element: HTMLElement) => element.focus())

class App extends Component {
  usage0 =
    'onSave: HotkeyCallback = (_event, context) => {\n  if (context.kind === \'chord\') {\n    console.log(context.hotkey, context.parsedChord)\n  }\n}\n\n<template>\n  {{useHotkey "Mod+[KeyS]" this.onSave}}\n</template>'
  usage1 = '{{useHotkey "Mod+K" this.increment requireReset=true}}'
  usage2 =
    '@tracked enabled = true\n\n<template>\n  {{useHotkey "Mod+E" this.runAction enabled=this.enabled}}\n</template>'
  usage3 =
    '{{useHotkey "Mod+1" this.openFirstTab}}\n{{useHotkey "Mod+[Digit2]" this.openSecondTab}}'
  usage4 =
    '{{useHotkey "Shift+ArrowUp" this.selectUp}}\n{{useHotkey "Alt+ArrowLeft" this.navigateBack}}\n{{useHotkey "Mod+Home" this.goToStart}}\n{{useHotkey "Control+PageUp" this.previousPage}}'
  usage5 =
    '{{useHotkey "Alt+F4" this.closeWindow}}\n{{useHotkey "Control+F5" this.hardRefresh}}\n{{useHotkey "Mod+F1" this.showHelp}}\n{{useHotkey "F12" this.openDevTools}}'
  usage6 =
    '{{useHotkey "Mod+Shift+S" this.saveAs}}\n{{useHotkey "Control+Alt+Shift+X" this.runAdvancedAction}}'
  usage7 =
    '{{useHotkey "Mod+Enter" this.submitForm}}\n{{useHotkey "Mod+Backspace" this.deleteWord}}\n{{useHotkey "Mod+Space" this.openPalette}}'
  usage8 =
    '<div {{onHotkey "Mod+B" this.sidebarAction}} tabindex="0">...</div>\n{{#if this.modalOpen}}\n  <div {{onHotkey "Escape" this.closeModal}} tabindex="0">...</div>\n{{/if}}\n<textarea {{onHotkey "Mod+S" this.saveEditor}}></textarea>'
  @tracked lastHotkey: Hotkey | null = null
  @tracked saveCount: number = 0
  @tracked incrementCount: number = 0
  @tracked enabled: boolean = true
  @tracked activeTab: number = 1
  @tracked navigationCount: number = 0
  @tracked functionKeyCount: number = 0
  @tracked multiModifierCount: number = 0
  @tracked editingKeyCount: number = 0
  @tracked modalOpen: boolean = false
  @tracked editorContent: string = ''
  @tracked sidebarShortcutCount: number = 0
  @tracked modalShortcutCount: number = 0
  @tracked editorShortcutCount: number = 0
  toggleEnabled = () => (this.enabled = !this.enabled)
  openModal = () => (this.modalOpen = true)
  closeModal = () => (this.modalOpen = false)
  stopClickPropagation = (e: Event) => e.stopPropagation()
  updateEditor = (e: Event) =>
    (this.editorContent = (e.currentTarget as HTMLInputElement).value)
  onModKeyS: HotkeyCallback = (_event, context) => {
    this.lastHotkey = context.hotkey
    this.saveCount = this.saveCount + 1
    console.log('Hotkey triggered:', context.hotkey)
    if (context.kind === 'chord') {
      console.log('Parsed hotkey:', context.parsedChord)
    }
  }
  onModK: HotkeyCallback = (_event, { hotkey }) => {
    this.lastHotkey = hotkey
    this.incrementCount = this.incrementCount + 1
  }
  onModE: HotkeyCallback = (_event, { hotkey }) => {
    this.lastHotkey = hotkey
    alert('This hotkey can be toggled!')
  }
  onMod1: HotkeyCallback = () => {
    this.lastHotkey = 'Mod+1'
    this.activeTab = 1
  }
  onModDigit2: HotkeyCallback = () => {
    this.lastHotkey = 'Mod+[Digit2]'
    this.activeTab = 2
  }
  onMod3: HotkeyCallback = () => {
    this.lastHotkey = 'Mod+3'
    this.activeTab = 3
  }
  onMod4: HotkeyCallback = () => {
    this.lastHotkey = 'Mod+4'
    this.activeTab = 4
  }
  onMod5: HotkeyCallback = () => {
    this.lastHotkey = 'Mod+5'
    this.activeTab = 5
  }
  onShiftArrowUp: HotkeyCallback = () => {
    this.lastHotkey = 'Shift+ArrowUp'
    this.navigationCount = this.navigationCount + 1
  }
  onShiftArrowDown: HotkeyCallback = () => {
    this.lastHotkey = 'Shift+ArrowDown'
    this.navigationCount = this.navigationCount + 1
  }
  onAltArrowLeft: HotkeyCallback = () => {
    this.lastHotkey = 'Alt+ArrowLeft'
    this.navigationCount = this.navigationCount + 1
  }
  onAltArrowRight: HotkeyCallback = () => {
    this.lastHotkey = 'Alt+ArrowRight'
    this.navigationCount = this.navigationCount + 1
  }
  onModHome: HotkeyCallback = () => {
    this.lastHotkey = 'Mod+Home'
    this.navigationCount = this.navigationCount + 1
  }
  onModEnd: HotkeyCallback = () => {
    this.lastHotkey = 'Mod+End'
    this.navigationCount = this.navigationCount + 1
  }
  onControlPageUp: HotkeyCallback = () => {
    this.lastHotkey = 'Control+PageUp'
    this.navigationCount = this.navigationCount + 1
  }
  onControlPageDown: HotkeyCallback = () => {
    this.lastHotkey = 'Control+PageDown'
    this.navigationCount = this.navigationCount + 1
  }
  onAltF4: HotkeyCallback = () => {
    this.lastHotkey = 'Alt+F4'
    this.functionKeyCount = this.functionKeyCount + 1
    alert('Alt+F4 pressed (normally closes window)')
  }
  onControlF5: HotkeyCallback = () => {
    this.lastHotkey = 'Control+F5'
    this.functionKeyCount = this.functionKeyCount + 1
  }
  onModF1: HotkeyCallback = () => {
    this.lastHotkey = 'Mod+F1'
    this.functionKeyCount = this.functionKeyCount + 1
  }
  onShiftF10: HotkeyCallback = () => {
    this.lastHotkey = 'Shift+F10'
    this.functionKeyCount = this.functionKeyCount + 1
  }
  onModShiftS: HotkeyCallback = () => {
    this.lastHotkey = 'Mod+Shift+S'
    this.multiModifierCount = this.multiModifierCount + 1
  }
  onModShiftZ: HotkeyCallback = () => {
    this.lastHotkey = 'Mod+Shift+Z'
    this.multiModifierCount = this.multiModifierCount + 1
  }
  get rawSelectAll(): RegisterableHotkey {
    return { key: 'A', ctrl: true, alt: true }
  }
  selectAll: HotkeyCallback = () => {
    this.lastHotkey = 'Control+Alt+A'
    this.multiModifierCount = this.multiModifierCount + 1
  }
  onControlShiftN: HotkeyCallback = () => {
    this.lastHotkey = 'Control+Shift+N'
    this.multiModifierCount = this.multiModifierCount + 1
  }
  onModAltT: HotkeyCallback = () => {
    this.lastHotkey = 'Mod+Alt+T'
    this.multiModifierCount = this.multiModifierCount + 1
  }
  onControlAltShiftX: HotkeyCallback = () => {
    this.lastHotkey = 'Control+Alt+Shift+X'
    this.multiModifierCount = this.multiModifierCount + 1
  }
  onModEnter: HotkeyCallback = () => {
    this.lastHotkey = 'Mod+Enter'
    this.editingKeyCount = this.editingKeyCount + 1
  }
  onShiftEnter: HotkeyCallback = () => {
    this.lastHotkey = 'Shift+Enter'
    this.editingKeyCount = this.editingKeyCount + 1
  }
  onModBackspace: HotkeyCallback = () => {
    this.lastHotkey = 'Mod+Backspace'
    this.editingKeyCount = this.editingKeyCount + 1
  }
  onModDelete: HotkeyCallback = () => {
    this.lastHotkey = 'Mod+Delete'
    this.editingKeyCount = this.editingKeyCount + 1
  }
  onControlTab: HotkeyCallback = () => {
    this.lastHotkey = 'Control+Tab'
    this.editingKeyCount = this.editingKeyCount + 1
  }
  onShiftTab: HotkeyCallback = () => {
    this.lastHotkey = 'Shift+Tab'
    this.editingKeyCount = this.editingKeyCount + 1
  }
  onModSpace: HotkeyCallback = () => {
    this.lastHotkey = 'Mod+Space'
    this.editingKeyCount = this.editingKeyCount + 1
  }
  get escape(): RegisterableHotkey {
    return { key: 'Escape' }
  }
  resetCounters: HotkeyCallback = () => {
    this.lastHotkey = null
    this.saveCount = 0
    this.incrementCount = 0
    this.navigationCount = 0
    this.functionKeyCount = 0
    this.multiModifierCount = 0
    this.editingKeyCount = 0
    this.activeTab = 1
  }
  onF12: HotkeyCallback = () => {
    this.lastHotkey = 'F12'
    this.functionKeyCount = this.functionKeyCount + 1
  }
  onModBSidebar: HotkeyCallback = () => {
    this.lastHotkey = 'Mod+B'
    this.sidebarShortcutCount = this.sidebarShortcutCount + 1
    alert(
      'Sidebar shortcut triggered! This only works when the sidebar area is focused.',
    )
  }
  onModNSidebar: HotkeyCallback = () => {
    this.lastHotkey = 'Mod+N'
    this.sidebarShortcutCount = this.sidebarShortcutCount + 1
  }
  onEscapeModal: HotkeyCallback = () => {
    this.lastHotkey = 'Escape'
    this.modalShortcutCount = this.modalShortcutCount + 1
    this.modalOpen = false
  }
  onModEnterModal: HotkeyCallback = () => {
    this.lastHotkey = 'Mod+Enter'
    this.modalShortcutCount = this.modalShortcutCount + 1
    alert('Modal submit shortcut!')
  }
  onModSEditor: HotkeyCallback = () => {
    this.lastHotkey = 'Mod+S'
    this.editorShortcutCount = this.editorShortcutCount + 1
    alert(
      `Editor content saved: "${this.editorContent.substring(0, 50)}${this.editorContent.length > 50 ? '...' : ''}"`,
    )
  }
  onModEditor: HotkeyCallback = () => {
    this.lastHotkey = 'Mod+/'
    this.editorShortcutCount = this.editorShortcutCount + 1
    this.editorContent = this.editorContent + '\n// Comment added via shortcut'
  }
  onModKEditor: HotkeyCallback = () => {
    this.lastHotkey = 'Mod+K'
    this.editorShortcutCount = this.editorShortcutCount + 1
    this.editorContent = ''
  }
  onJ: HotkeyCallback = () => {
    this.lastHotkey = 'J'
    this.editorShortcutCount = this.editorShortcutCount + 1
  }

  <template>
    {{useHotkey 'Mod+[KeyS]' this.onModKeyS}}
    {{useHotkey 'Mod+K' this.onModK requireReset=true}}
    {{useHotkey 'Mod+E' this.onModE enabled=this.enabled}}
    {{useHotkey 'Mod+1' this.onMod1}}
    {{useHotkey 'Mod+[Digit2]' this.onModDigit2}}
    {{useHotkey 'Mod+3' this.onMod3}}
    {{useHotkey 'Mod+4' this.onMod4}}
    {{useHotkey 'Mod+5' this.onMod5}}
    {{useHotkey 'Shift+ArrowUp' this.onShiftArrowUp}}
    {{useHotkey 'Shift+ArrowDown' this.onShiftArrowDown}}
    {{useHotkey 'Alt+ArrowLeft' this.onAltArrowLeft}}
    {{useHotkey 'Alt+ArrowRight' this.onAltArrowRight}}
    {{useHotkey 'Mod+Home' this.onModHome}}
    {{useHotkey 'Mod+End' this.onModEnd}}
    {{useHotkey 'Control+PageUp' this.onControlPageUp}}
    {{useHotkey 'Control+PageDown' this.onControlPageDown}}
    {{useHotkey 'Alt+F4' this.onAltF4}}
    {{useHotkey 'Control+F5' this.onControlF5}}
    {{useHotkey 'Mod+F1' this.onModF1}}
    {{useHotkey 'Shift+F10' this.onShiftF10}}
    {{useHotkey 'Mod+Shift+S' this.onModShiftS}}
    {{useHotkey 'Mod+Shift+Z' this.onModShiftZ}}
    {{useHotkey this.rawSelectAll this.selectAll}}
    {{useHotkey 'Control+Shift+N' this.onControlShiftN}}
    {{useHotkey 'Mod+Alt+T' this.onModAltT}}
    {{useHotkey 'Control+Alt+Shift+X' this.onControlAltShiftX}}
    {{useHotkey 'Mod+Enter' this.onModEnter}}
    {{useHotkey 'Shift+Enter' this.onShiftEnter}}
    {{useHotkey 'Mod+Backspace' this.onModBackspace}}
    {{useHotkey 'Mod+Delete' this.onModDelete}}
    {{useHotkey 'Control+Tab' this.onControlTab}}
    {{useHotkey 'Shift+Tab' this.onShiftTab}}
    {{useHotkey 'Mod+Space' this.onModSpace}}
    {{useHotkey this.escape this.resetCounters}}
    {{useHotkey 'F12' this.onF12}}

    {{useHotkey 'J' this.onJ}}
    <div class='app'>
      <header>
        <h1>useHotkey</h1>
        <p>
          Register keyboard shortcuts with callback context containing the hotkey
          and parsed hotkey information.
        </p>
      </header>

      <main>
        <section class='demo-section'>
          <h2>Basic Hotkey</h2>
          <p>
            Press
            <kbd>{{formatForDisplay 'Mod+[KeyS]'}}</kbd>
            to trigger the physical S position
          </p>
          <div class='counter'>Save triggered: {{this.saveCount}}x</div>
          <pre class='code-block'>{{this.usage0}}</pre>
        </section>

        <section class='demo-section'>
          <h2>With requireReset</h2>
          <p>
            Hold
            <kbd>{{formatForDisplay 'Mod+K'}}</kbd>
            — only increments once until you release all keys
          </p>
          <div class='counter'>Increment: {{this.incrementCount}}</div>
          <p class='hint'>
            This prevents repeated triggering while holding the keys down. Release
            all keys to allow re-triggering.
          </p>
          <pre class='code-block'>{{this.usage1}}</pre>
        </section>

        <section class='demo-section'>
          <h2>Conditional Hotkey</h2>
          <p>
            <kbd>{{formatForDisplay 'Mod+E'}}</kbd>
            is currently
            <strong>{{if this.enabled 'enabled' 'disabled'}}</strong>
          </p>
          <button {{on 'click' this.toggleEnabled}}>
            {{if this.enabled 'Disable' 'Enable'}}
            Hotkey
          </button>
          <pre class='code-block'>{{this.usage2}}</pre>
        </section>

        <section class='demo-section'>
          <h2>Number Key Combinations</h2>
          <p>
            Tab 2 uses the physical number-row position (
            <code>Mod+[Digit2]</code>), even when that key produces a different
            character. The other tabs follow logical digits.
          </p>
          <div class='hotkey-grid'>
            <div>
              <kbd>{{formatForDisplay 'Mod+1'}}</kbd>
              → Tab 1
            </div>
            <div>
              <kbd>{{formatForDisplay 'Mod+[Digit2]'}}</kbd>
              → Tab 2
            </div>
            <div>
              <kbd>{{formatForDisplay 'Mod+3'}}</kbd>
              → Tab 3
            </div>
            <div>
              <kbd>{{formatForDisplay 'Mod+4'}}</kbd>
              → Tab 4
            </div>
            <div>
              <kbd>{{formatForDisplay 'Mod+5'}}</kbd>
              → Tab 5
            </div>
          </div>
          <div class='counter'>Active Tab: {{this.activeTab}}</div>
          <pre class='code-block'>{{this.usage3}}</pre>
        </section>

        <section class='demo-section'>
          <h2>Navigation Key Combinations</h2>
          <p>Selection and navigation shortcuts:</p>
          <div class='hotkey-grid'>
            <div>
              <kbd>{{formatForDisplay 'Shift+ArrowUp'}}</kbd>
              — Select up
            </div>
            <div>
              <kbd>{{formatForDisplay 'Shift+ArrowDown'}}</kbd>
              — Select down
            </div>
            <div>
              <kbd>{{formatForDisplay 'Alt+ArrowLeft'}}</kbd>
              — Navigate back
            </div>
            <div>
              <kbd>{{formatForDisplay 'Alt+ArrowRight'}}</kbd>
              — Navigate forward
            </div>
            <div>
              <kbd>{{formatForDisplay 'Mod+Home'}}</kbd>
              — Go to start
            </div>
            <div>
              <kbd>{{formatForDisplay 'Mod+End'}}</kbd>
              — Go to end
            </div>
            <div>
              <kbd>{{formatForDisplay 'Control+PageUp'}}</kbd>
              — Previous page
            </div>
            <div>
              <kbd>{{formatForDisplay 'Control+PageDown'}}</kbd>
              — Next page
            </div>
          </div>
          <div class='counter'>
            Navigation triggered:
            {{this.navigationCount}}x
          </div>
          <pre class='code-block'>{{this.usage4}}</pre>
        </section>

        <section class='demo-section'>
          <h2>Function Key Combinations</h2>
          <p>System and application shortcuts:</p>
          <div class='hotkey-grid'>
            <div>
              <kbd>{{formatForDisplay 'Alt+F4'}}</kbd>
              — Close window
            </div>
            <div>
              <kbd>{{formatForDisplay 'Control+F5'}}</kbd>
              — Hard refresh
            </div>
            <div>
              <kbd>{{formatForDisplay 'Mod+F1'}}</kbd>
              — Help
            </div>
            <div>
              <kbd>{{formatForDisplay 'Shift+F10'}}</kbd>
              — Context menu
            </div>
            <div>
              <kbd>{{formatForDisplay 'F12'}}</kbd>
              — DevTools
            </div>
          </div>
          <div class='counter'>
            Function keys triggered:
            {{this.functionKeyCount}}x
          </div>
          <pre class='code-block'>{{this.usage5}}</pre>
        </section>

        <section class='demo-section'>
          <h2>Multi-Modifier Combinations</h2>
          <p>Complex shortcuts with multiple modifiers:</p>
          <div class='hotkey-grid'>
            <div>
              <kbd>{{formatForDisplay 'Mod+Shift+S'}}</kbd>
              — Save As
            </div>
            <div>
              <kbd>{{formatForDisplay 'Mod+Shift+Z'}}</kbd>
              — Redo
            </div>
            <div>
              <kbd>{{formatForDisplay 'Control+Alt+A'}}</kbd>
              — Special action
            </div>
            <div>
              <kbd>{{formatForDisplay 'Control+Shift+N'}}</kbd>
              — New incognito
            </div>
            <div>
              <kbd>{{formatForDisplay 'Mod+Alt+T'}}</kbd>
              — Toggle theme
            </div>
            <div>
              <kbd>{{formatForDisplay 'Control+Alt+Shift+X'}}</kbd>
              — Triple modifier
            </div>
          </div>
          <div class='counter'>
            Multi-modifier triggered:
            {{this.multiModifierCount}}x
          </div>
          <pre class='code-block'>{{this.usage6}}</pre>
        </section>

        <section class='demo-section'>
          <h2>Editing Key Combinations</h2>
          <p>Text editing and form shortcuts:</p>
          <div class='hotkey-grid'>
            <div>
              <kbd>{{formatForDisplay 'Mod+Enter'}}</kbd>
              — Submit form
            </div>
            <div>
              <kbd>{{formatForDisplay 'Shift+Enter'}}</kbd>
              — New line
            </div>
            <div>
              <kbd>{{formatForDisplay 'Mod+Backspace'}}</kbd>
              — Delete word
            </div>
            <div>
              <kbd>{{formatForDisplay 'Mod+Delete'}}</kbd>
              — Delete forward
            </div>
            <div>
              <kbd>{{formatForDisplay 'Control+Tab'}}</kbd>
              — Next tab
            </div>
            <div>
              <kbd>{{formatForDisplay 'Shift+Tab'}}</kbd>
              — Previous field
            </div>
            <div>
              <kbd>{{formatForDisplay 'Mod+Space'}}</kbd>
              — Toggle
            </div>
          </div>
          <div class='counter'>
            Editing keys triggered:
            {{this.editingKeyCount}}x
          </div>
          <pre class='code-block'>{{this.usage7}}</pre>
        </section>

        {{#if this.lastHotkey}}<div class='info-box'>
            <strong>Last triggered:</strong>
            {{formatForDisplay this.lastHotkey}}
          </div>{{/if}}

        <p class='hint'>
          Press
          <kbd>Escape</kbd>
          to reset all counters
        </p>

        <section class='demo-section scoped-section'>
          <h2>Scoped Keyboard Shortcuts</h2>
          <p>
            Attach shortcuts to a DOM element with the
            <code>onHotkey</code>
            modifier. This allows different shortcuts to work in different parts of
            your application.
          </p>

          <div class='scoped-grid'>

            <div
              class='scoped-area'
              {{onHotkey 'Mod+B' this.onModBSidebar}}
              {{onHotkey 'Mod+N' this.onModNSidebar}}
              tabindex={{0}}
            >
              <h3>Sidebar (Scoped Area)</h3>
              <p>Click here to focus, then try:</p>
              <div class='hotkey-list'>
                <div>
                  <kbd>{{formatForDisplay 'Mod+B'}}</kbd>
                  — Trigger sidebar action
                </div>
                <div>
                  <kbd>{{formatForDisplay 'Mod+N'}}</kbd>
                  — New item
                </div>
              </div>
              <div class='counter'>
                Sidebar shortcuts:
                {{this.sidebarShortcutCount}}x
              </div>
              <p class='hint'>
                These shortcuts only work when this sidebar area is focused or
                contains focus.
              </p>
            </div>

            <div class='scoped-area'>
              <h3>Modal Dialog</h3>
              <button {{on 'click' this.openModal}}>Open Modal</button>
              {{#if this.modalOpen}}<div
                  class='modal-overlay'
                  {{on 'click' this.closeModal}}
                >
                  <div
                    class='modal-content'
                    {{onHotkey 'Escape' this.onEscapeModal}}
                    {{onHotkey 'Mod+Enter' this.onModEnterModal}}
                    {{autofocus}}
                    tabindex={{0}}
                    {{on 'click' this.stopClickPropagation}}
                  >
                    <h3>Modal Dialog (Scoped)</h3>
                    <p>Try these shortcuts while modal is open:</p>
                    <div class='hotkey-list'>
                      <div>
                        <kbd>{{formatForDisplay 'Escape'}}</kbd>
                        — Close modal
                      </div>
                      <div>
                        <kbd>{{formatForDisplay 'Mod+Enter'}}</kbd>
                        — Submit
                      </div>
                    </div>
                    <div class='counter'>
                      Modal shortcuts:
                      {{this.modalShortcutCount}}x
                    </div>
                    <p class='hint'>
                      These shortcuts only work when the modal is open and focused.
                      The Escape key here won't conflict with the global Escape
                      handler.
                    </p>
                    <button {{on 'click' this.closeModal}}>Close</button>
                  </div>
                </div>{{/if}}
            </div>

            <div class='scoped-area'>
              <h3>Text Editor (Scoped)</h3>
              <p>Focus the editor below and try:</p>
              <div class='hotkey-list'>
                <div>
                  <kbd>{{formatForDisplay 'Mod+S'}}</kbd>
                  — Save editor content
                </div>
                <div>
                  <kbd>{{formatForDisplay 'Mod+/'}}</kbd>
                  — Add comment
                </div>
                <div>
                  <kbd>{{formatForDisplay 'Mod+K'}}</kbd>
                  — Clear editor
                </div>
                <div>
                  <kbd>J</kbd>
                  — Single key (test ignoreInputs)
                </div>
              </div>
              <textarea
                {{onHotkey 'Mod+S' this.onModSEditor}}
                {{onHotkey 'Mod+/' this.onModEditor}}
                {{onHotkey 'Mod+K' this.onModKEditor}}
                class='scoped-editor'
                value={{this.editorContent}}
                {{on 'input' this.updateEditor}}
                placeholder='Focus here and try the shortcuts above...'
                rows={{8}}
              ></textarea>
              <div class='counter'>
                Editor shortcuts:
                {{this.editorShortcutCount}}x
              </div>
              <p class='hint'>
                These shortcuts only work when the editor is focused. Notice that
                <kbd>{{formatForDisplay 'Mod+S'}}</kbd>
                here doesn't conflict with the global
                <kbd>{{formatForDisplay 'Mod+S'}}</kbd>
                shortcut.
              </p>
            </div>
          </div>

          <pre class='code-block'>{{this.usage8}}</pre>
        </section>
      </main>

    </div>
  </template>
}
export default App