Register hotkeys, display a beautiful overlay with ?, handle sequences, groups, and modifiers — in 5 lines.
Register hotkeys with .register(). Supports modifiers, sequences, and groups out of the box.
Press ? to reveal a polished shortcut sheet, grouped and labeled. Like GitHub, Figma, and Linear.
Support for vim-style sequences like g then h. First-class citizen, not an afterthought.
Dark, light, or auto (follows system preference). CSS variables let you fully customize the look.
No React, no Lodash, no moment.js. Just a clean TypeScript class you drop into any project.
Ships as ESM, CommonJS, and TypeScript types. Works everywhere: Vite, Next.js, webpack, CDN.
Press ? anywhere to open the shortcut overlay, or try the shortcuts below
npm install hotkey-hint
yarn add hotkey-hint
pnpm add hotkey-hint
<script type="module"> import HotkeyHint from 'https://esm.sh/hotkey-hint'; </script>
import HotkeyHint from 'hotkey-hint'; const hh = new HotkeyHint({ theme: 'auto' }); hh.registerAll([ { keys: 'ctrl+k', description: 'Open command palette', action: () => openCommandPalette(), }, { keys: 'ctrl+s', description: 'Save document', action: () => save(), }, ]); // Press ? to open the overlay automatically
hh.registerAll([ // Navigation group { keys: 'g then h', description: 'Go home', group: 'Navigation', action }, { keys: 'g then p', description: 'Go to profile', group: 'Navigation', action }, // Editor group { keys: 'ctrl+b', description: 'Bold', group: 'Editor', action }, { keys: 'ctrl+i', description: 'Italic', group: 'Editor', action }, { keys: 'ctrl+u', description: 'Underline', group: 'Editor', action }, ]);
// Vim-style sequences: press "g" then "h" within 2 seconds hh.register({ keys: 'g then h', description: 'Go to home', group: 'Navigation', action: () => router.push('/'), }); hh.register({ keys: 'g then s', description: 'Go to settings', group: 'Navigation', action: () => router.push('/settings'), });
import { useEffect } from 'react'; import HotkeyHint from 'hotkey-hint'; function useHotkeys(hotkeys, deps = []) { useEffect(() => { const hh = new HotkeyHint({ theme: 'auto' }); hh.registerAll(hotkeys); return () => hh.destroy(); // cleanup on unmount }, deps); } // In your component: useHotkeys([ { keys: 'ctrl+k', description: 'Search', action: openSearch }, { keys: 'ctrl+/', description: 'Toggle sidebar', action: toggleSidebar }, ]);
| Option | Type | Default | Description |
|---|---|---|---|
| triggerKey | string | "?" | Key that opens the overlay |
| theme | "dark" | "light" | "auto" | "auto" | Color theme. Auto follows system preference |
| position | "center" | "bottom-right" | "bottom-left" | "center" | Where the overlay panel appears |
| title | string | "Keyboard Shortcuts" | Title shown at the top of the overlay |
| zIndex | number | 9999 | CSS z-index for the overlay |
| Method | Returns | Description |
|---|---|---|
| .register(hotkey) | this | Register a single hotkey. Chainable. |
| .registerAll(hotkeys[]) | this | Register multiple hotkeys at once. Chainable. |
| .unregister(keys) | this | Remove a registered hotkey by its key string. |
| .show() | void | Programmatically show the overlay. |
| .hide() | void | Programmatically hide the overlay. |
| .toggle() | void | Show if hidden, hide if shown. |
| .destroy() | void | Remove all listeners and DOM elements. Call on unmount. |