-
-
Notifications
You must be signed in to change notification settings - Fork 34
Description
TanStack Hotkeys version
v0.4.1
Framework/Library version
React v19 (Next.js 15)
Describe the bug and the steps to reproduce it
On macOS, the Option (Alt) key acts as a character composer. Pressing Option+- produces an en-dash (–, U+2013), so event.key is "–" instead of "-". This causes useHotkey("Alt+-", callback) to never fire.
The library correctly handles this remapping for letters and digits by falling back to event.code in matchesKeyboardEvent (in match.ts):
// These fallbacks exist and work:
if (event.code?.startsWith("Key")) { /* letter fallback ✅ */ }
if (event.code?.startsWith("Digit")) { /* digit fallback ✅ */ }
return false; // ← punctuation keys like "Minus" fall through here ❌There is no equivalent fallback for punctuation keys whose event.code values (Minus, Equal, Slash, BracketLeft, etc.) don't start with Key or Digit.
Steps to reproduce:
- On macOS with an English (US) keyboard layout
- Register
useHotkey("Alt+-", callback) - Press Option + minus key
- Callback never fires
For comparison, useHotkey("Alt+1", callback) works correctly because it hits the Digit code fallback.
All PUNCTUATION_KEYS are affected when combined with Alt on macOS:
| Hotkey | event.key on macOS |
event.code |
Matched? |
|---|---|---|---|
Alt+- |
– (en-dash) |
Minus |
No |
Alt+= |
≠ |
Equal |
No |
Alt+/ |
÷ |
Slash |
No |
Alt+[ |
" |
BracketLeft |
No |
Alt+] |
' |
BracketRight |
No |
Alt+\ |
« |
Backslash |
No |
Alt+, |
≤ |
Comma |
No |
Alt+. |
≥ |
Period |
No |
Suggested fix — add a punctuation code fallback in matchesKeyboardEvent, after the existing Digit fallback:
const PUNCTUATION_CODE_MAP: Record<string, string> = {
Minus: "-",
Equal: "=",
Slash: "/",
BracketLeft: "[",
BracketRight: "]",
Backslash: "\\",
Comma: ",",
Period: ".",
Backquote: "`",
};
if (event.code && event.code in PUNCTUATION_CODE_MAP) {
return PUNCTUATION_CODE_MAP[event.code] === hotkeyKey;
}Your Minimal, Reproducible Example - (Sandbox Highly Recommended)
https://stackblitz.com/edit/vitejs-vite-6pdg1d7r?file=src%2FApp.tsx
Screenshots or Videos (Optional)
No response
Do you intend to try to help solve this bug with your own PR?
Yes, I am also opening a PR that solves the problem along side this issue
Terms & Code of Conduct
- I agree to follow this project's Code of Conduct
- I understand that if my bug cannot be reliable reproduced in a debuggable environment, it will probably not be fixed and this issue may even be closed.