{"id":13415398,"url":"https://github.com/github/hotkey","last_synced_at":"2025-05-11T16:30:27.762Z","repository":{"id":37550036,"uuid":"166252898","full_name":"github/hotkey","owner":"github","description":"Trigger an action on an element with a keyboard shortcut.","archived":false,"fork":false,"pushed_at":"2024-10-14T19:45:42.000Z","size":1124,"stargazers_count":3218,"open_issues_count":9,"forks_count":96,"subscribers_count":233,"default_branch":"main","last_synced_at":"2024-10-29T11:29:55.103Z","etag":null,"topics":["decorator","shortcuts"],"latest_commit_sha":null,"homepage":"https://github.github.com/hotkey/","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/github.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":"CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-01-17T15:56:28.000Z","updated_at":"2024-10-25T09:38:10.000Z","dependencies_parsed_at":"2023-09-25T03:53:21.085Z","dependency_job_id":"c3ed6ff9-3971-4b69-a77b-074a3429cde6","html_url":"https://github.com/github/hotkey","commit_stats":{"total_commits":223,"total_committers":21,"mean_commits":"10.619047619047619","dds":0.6995515695067265,"last_synced_commit":"bc70e3d21e4e7a27544643c43b125c8ee0672004"},"previous_names":[],"tags_count":39,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/github%2Fhotkey","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/github%2Fhotkey/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/github%2Fhotkey/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/github%2Fhotkey/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/github","download_url":"https://codeload.github.com/github/hotkey/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":251565777,"owners_count":21609979,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["decorator","shortcuts"],"created_at":"2024-07-30T21:00:48.169Z","updated_at":"2025-04-29T18:55:56.678Z","avatar_url":"https://github.com/github.png","language":"JavaScript","readme":"# Hotkey Behavior\n\n```html\n\u003cbutton data-hotkey=\"Shift+?\"\u003eShow help dialog\u003c/button\u003e\n```\n\nTrigger an action on a target element when the hotkey (key or sequence of keys) is pressed\non the keyboard. This triggers a focus event on form fields, or a click event on\nother elements.\n\nThe hotkey can be scoped to a form field:\n\n```html\n\u003cbutton data-hotkey-scope=\"text-area\" data-hotkey=\"Meta+d\" onclick=\"alert('clicked')\"\u003e\n  press meta+d in text area to click this button\n\u003c/button\u003e\n\n\u003ctextarea id=\"text-area\"\u003etext area\u003c/textarea\u003e\n```\n\nBy default, hotkeys are extracted from a target element's `data-hotkey`\nattribute, but this can be overridden by passing the hotkey to the registering\nfunction (`install`) as a parameter.\n\n## How is this used on GitHub?\n\nAll shortcuts (for example `g i`, `.`, `Meta+k`) within GitHub use hotkey to declare shortcuts in server side templates. This is used on almost every page on GitHub.\n\n## Installation\n\n```\n$ npm install @github/hotkey\n```\n\n## Usage\n\n### HTML\n\n```html\n\u003c!-- Single character hotkey: triggers when \"j\" is pressed--\u003e\n\u003ca href=\"/page/2\" data-hotkey=\"j\"\u003eNext\u003c/a\u003e\n\u003c!-- Multiple hotkey aliases: triggers on both \"s\" and \"/\" --\u003e\n\u003ca href=\"/search\" data-hotkey=\"s,/\"\u003eSearch\u003c/a\u003e\n\u003c!-- Key-sequence hotkey: triggers when \"g\" is pressed followed by \"c\"--\u003e\n\u003ca href=\"/rails/rails\" data-hotkey=\"g c\"\u003eCode\u003c/a\u003e\n\u003c!-- Hotkey with modifiers: triggers when \"Control\", \"Alt\", and \"h\" are pressed at the same time --\u003e\n\u003ca href=\"/help\" data-hotkey=\"Control+Alt+h\"\u003eHelp\u003c/a\u003e\n\u003c!-- Special \"Mod\" modifier localizes to \"Meta\" on mac, \"Control\" on Windows or Linux--\u003e\n\u003ca href=\"/settings\" data-hotkey=\"Mod+s\"\u003eSearch\u003c/a\u003e\n```\n\nSee [the list of `KeyboardEvent` key values](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key/Key_Values) for a list of supported key values.\n\n### JS\n\n```js\nimport {install} from '@github/hotkey'\n\n// Install all the hotkeys on the page\nfor (const el of document.querySelectorAll('[data-hotkey]')) {\n  install(el)\n}\n```\n\nAlternatively, the hotkey(s) can be passed to the `install` function as a parameter e.g.:\n\n```js\nfor (const el of document.querySelectorAll('[data-shortcut]')) {\n  install(el, el.dataset.shortcut)\n}\n```\n\nTo unregister a hotkey from an element, use `uninstall`:\n\n```js\nimport {uninstall} from '@github/hotkey'\n\nfor (const el of document.querySelectorAll('[data-hotkey]')) {\n  uninstall(el)\n}\n```\n\nBy default form elements (such as `input`,`textarea`,`select`) or elements with `contenteditable` will call `focus()` when the hotkey is triggered. All other elements trigger a `click()`. All elements, regardless of type, will emit a cancellable `hotkey-fire` event, so you can customize the behaviour, if you so choose:\n\n```js\nfor (const el of document.querySelectorAll('[data-shortcut]')) {\n  install(el, el.dataset.shortcut)\n\n  if (el.matches('.frobber')) {\n    el.addEventListener('hotkey-fire', event =\u003e {\n      // ensure the default `focus()`/`click()` is prevented:\n      event.preventDefault()\n\n      // Use a custom behaviour instead\n      frobulateFrobber(event.target)\n    })\n  }\n}\n```\n\n## Hotkey string format\n\n1. Hotkey matches against the `event.key`, and uses standard W3C key names for keys and modifiers as documented in [UI Events KeyboardEvent key Values](https://www.w3.org/TR/uievents-key/).\n2. At minimum a hotkey string must specify one bare key.\n3. Multiple hotkeys (aliases) are separated by a `,`. For example the hotkey `a,b` would activate if the user typed `a` or `b`.\n4. Multiple keys separated by a blank space represent a key sequence. For example the hotkey `g n` would activate when a user types the `g` key followed by the `n` key.\n5. Modifier key combos are separated with a `+` and are prepended to a key in a consistent order as follows: `\"Control+Alt+Meta+Shift+KEY\"`.\n6. `\"Mod\"` is a special modifier that localizes to `Meta` on MacOS/iOS, and `Control` on Windows/Linux.\n   1. `\"Mod+\"` can appear in any order in a hotkey string. For example: `\"Mod+Alt+Shift+KEY\"`\n   2. Neither the `Control` or `Meta` modifiers should appear in a hotkey string with `Mod`.\n7. `\"Plus\"` and `\"Space\"` are special key names to represent the `+` and ` ` keys respectively, because these symbols cannot be represented in the normal hotkey string syntax.\n8. You can use the comma key `,` as a hotkey, e.g. `a,,` would activate if the user typed `a` or `,`. `Control+,,x` would activate for `Control+,` or `x`.\n9. `\"Shift\"` should be included if it would be held and the key is uppercase: ie, `Shift+A` not `A`\n   1. MacOS outputs lowercase key names when `Meta+Shift` is held (ie, `Meta+Shift+a`). In an attempt to normalize this, `hotkey` will automatically map these key names to uppercase, so the uppercase keys should still be used (ie, `\"Meta+Shift+A\"` or `\"Mod+Shift+A\"`). **However**, this normalization only works on US keyboard layouts.\n\n### Example\n\nThe following hotkey would match if the user typed the key sequence `a` and then `b`, OR if the user held down the `Control`, `Alt` and `/` keys at the same time.\n\n```js\n'a b,Control+Alt+/'\n```\n\n🔬 **Hotkey Mapper** is a tool to help you determine the correct hotkey string for your key combination: \u003chttps://github.github.io/hotkey/hotkey_mapper.html\u003e\n\n#### Key-sequence considerations\n\nTwo-key-sequences such as `g c` and `g i` are stored\nunder the 'g' key in a nested object with 'c' and 'i' keys.\n\n```\nmappings =\n  'c'     : \u003ca href=\"/rails/rails/issues/new\" data-hotkey=\"c\"\u003eNew Issue\u003c/a\u003e\n  'g'     :\n    'c'   : \u003ca href=\"/rails/rails\" data-hotkey=\"g c\"\u003eCode\u003c/a\u003e\n    'i'   : \u003ca href=\"/rails/rails/issues\" data-hotkey=\"g i\"\u003eIssues\u003c/a\u003e\n```\n\nIn this example, both `g c` and `c` could be available as hotkeys on the\nsame page, but `g c` and `g` can't coexist. If the user presses\n`g`, the `c` hotkey will be unavailable for 1500 ms while we\nwait for either `g c` or `g i`.\n\n## Accessibility considerations\n\n### Character Key Shortcuts\n\nPlease note that adding this functionality to your site can be a drawback for\ncertain users. Providing a way in your system to disable hotkeys or remap\nthem makes sure that those users can still use your site (given that it's\naccessible to those users).\n\nSee [\"Understanding Success Criterion 2.1.4: Character Key Shortcuts\"](https://www.w3.org/WAI/WCAG21/Understanding/character-key-shortcuts.html)\nfor further reading on this topic.\n\n### Interactive Elements\n\nWherever possible, hotkeys should be add to [interactive and focusable elements](https://html.spec.whatwg.org/#interactive-content). If a static element must be used, please follow the guideline in [\"Adding keyboard-accessible actions to static HTML elements\"](https://www.w3.org/WAI/WCAG21/Techniques/client-side-script/SCR29.html).\n\n## Development\n\n```\nnpm install\nnpm test\n```\n\n## License\n\nDistributed under the MIT license. See LICENSE for details.\n","funding_links":[],"categories":["JavaScript","others","Uncategorized","Programming Languages"],"sub_categories":["Uncategorized","JavaScript"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgithub%2Fhotkey","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgithub%2Fhotkey","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgithub%2Fhotkey/lists"}