@github/hotkey

repository·main·Indexed 25 days ago

https://github.com/github/hotkey

A library for declaring and triggering keyboard shortcuts on web elements. It supports single keys, aliases, sequences, and modifier combinations via HTML data attributes or JavaScript. Features include a SequenceTracker for multi-key flows, a RadixTrie for efficient lookup, and utilities like eventToHotkeyString and normalizeHotkey for standardizing keyboard input across platforms.

Tokens
2.3K
Snippets
5
Records
16
Agent score
84%

What's inside @github/hotkey

  1. Use HTML data attributes for hotkeys

    main

    You can declare hotkeys directly in your HTML using the data-hotkey attribute. This allows for various formats including single characters, aliases, sequences, and modifiers.

    Supported formats:

    • Single character: data-hotkey="j" (triggers on 'j')
    • Aliases: data-hotkey="s,/" (triggers on 's' or '/')
    • Key sequences: data-hotkey="g c" (triggers on 'g' followed by 'c')
    • Modifiers: data-hotkey="Control+Alt+h" (triggers on Control, Alt, and 'h' simultaneously)
    • Special 'Mod' modifier: data-hotkey="Mod+s" (localizes to Meta on macOS/iOS, and Control on Windows/Linux)

    Scoping hotkeys: Use data-hotkey-scope to restrict hotkeys to specific contexts (e.g., a text area).

    <!-- Single character hotkey -->
    <a href="/page/2" data-hotkey="j">Next</a>
    
    <!-- Multiple hotkey aliases -->
    <a href="/search" data-hotkey="s,/">Search</a>
    
    <!-- Key-sequence hotkey -->
    <a href="/rails/rails" data-hotkey="g c">Code</a>
    
    <!-- Hotkey with modifiers -->
    <a href="/help" data-hotkey="Control+Alt+h">Help</a>
    
    <!-- Scoped hotkey -->
    <button data-hotkey-scope="text-area" data-hotkey="Meta+d" onclick="alert('clicked')">
      press meta+d in text area to click this button
    </button>
    <textarea id="text-area">text area</textarea>
  2. Customize hotkey behavior with 'hotkey-fire' event

    main

    By default, form elements (input, textarea, select) or contenteditable elements call .focus() when triggered, while all other elements trigger a .click().

    All elements emit a cancellable hotkey-fire event. You can listen for this event and call event.preventDefault() to override the default behavior with custom logic.

    import {install} from '@github/hotkey'
    
    for (const el of document.querySelectorAll('[data-shortcut]')) {
      install(el, el.dataset.shortcut)
    
      if (el.matches('.frobber')) {
        el.addEventListener('hotkey-fire', event => {
          // prevent the default focus() or click()
          event.preventDefault()
    
          // Execute custom behavior
          frobulateFrobber(event.target)
        })
      }
    }
  3. Register and unregister hotkeys with JS

    main

    Use the install function to activate hotkeys on elements. You can either rely on the data-hotkey attribute or pass a specific hotkey string as a second argument. Use uninstall to remove hotkeys from an element.

    import {install, uninstall} from '@github/hotkey'
    
    // Install all hotkeys found in the DOM via data-hotkey attribute
    for (const el of document.querySelectorAll('[data-hotkey]')) {
      install(el)
    }
    
    // Install hotkeys using a custom attribute (e.g., data-shortcut)
    for (const el of document.querySelectorAll('[data-shortcut]')) {
      install(el, el.dataset.shortcut)
    }
    
    // Unregister hotkeys from elements
    for (const el of document.querySelectorAll('[data-hotkey]')) {
      uninstall(el)
    }
  4. Hotkey string format specification

    main

    Hotkey strings follow these rules:

    • Key Names: Uses standard W3C KeyboardEvent key names.
    • Aliases: Separate multiple hotkeys with a comma (,). Example: a,b.
    • Sequences: Separate keys in a sequence with a space. Example: g n.
    • Modifiers: Use + to combine modifiers and keys. Order: "Control+Alt+Meta+Shift+KEY".
    • Mod Modifier: Mod localizes to Meta on macOS/iOS and Control on Windows/Linux. Do not use Control or Meta in the same string as Mod.
    • Special Keys: Use Plus for + and Space for the space bar.
    • Comma Key: Use ,, to represent the comma key.
    • Case Sensitivity: Use uppercase for keys that require Shift (e.g., Shift+A). Note: Automatic normalization to uppercase for US keyboard layouts is supported.
  5. Convert a KeyboardEvent to a hotkey string with `eventToHotkeyString`

    main

    Use eventToHotkeyString to transform a KeyboardEvent into a standardized NormalizedHotkeyString. This is useful for comparing user input against predefined hotkey strings. The function handles platform-specific quirks, such as mapping macOS symbol layers and uppercase characters back to their base keys, and replaces certain symbols with synthetic names like Space or Plus to maintain compatibility with the hotkey string format.

    Supported modifier order: Control, Alt, Meta, Shift.

    document.addEventListener('keydown', function(event) {
      if (eventToHotkeyString(event) === 'h') ...
    })
  6. Normalize a hotkey string with `normalizeHotkey`

    main

    Use normalizeHotkey to ensure a raw hotkey string follows the standard format required for comparison with strings produced by eventToHotkeyString.

    Normalization performs the following:

    • Replaces the Mod modifier with Meta on Apple platforms (Mac, iPod, iPhone, iPad) or Control on other platforms.
    • Sorts modifiers into a consistent order: Control, Alt, Meta, Shift.

    Note: The platform parameter is primarily intended for mocking navigator.platform in testing environments; otherwise, it defaults to window.navigator.platform.

  7. Normalize a hotkey sequence string

    main
    Use normalizeSequence to take a raw string of hotkeys (separated by spaces) and return a NormalizedSequenceString. This ensures that each individual hotkey within the sequence is normalized using normalizeHotkey.
  8. Uninstall hotkeys from an element

    main
    Use the uninstall function to remove all hotkey registrations associated with a specific element. This cleans up the internal Radix Trie and, if no other hotkeys are registered, removes the global keydown listener from the document.
  9. Install hotkeys on an element

    main

    Use the install function to register an element to respond to specific hotkey sequences. You can provide the hotkey string explicitly, or the function will attempt to read it from the element's data-hotkey attribute.

    When install is called for the first time, it attaches a global keydown listener to the document. If the element is a form field, the hotkey will only trigger if the element's id matches the data-hotkey-scope attribute of the target element.