`useKeyHold` / `KeyStateTracker` latches a modifier forever when a `keyup` is swallowed without a `blur` (e.g. macOS Cmd+Shift+4)
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 719
- Forks
- 47
- Avg merge
- 5d 5h
- Merged PRs (30d)
- 1
Description
TanStack Hotkeys version
10.0.0
Framework/Library version
React v19.2.0
Describe the bug and the steps to reproduce it
useKeyHold('Shift') (and every consumer of the global KeyStateTracker) can get permanently stuck reporting a modifier as held. The tracker only learns a key was released from a discrete keyup event, and its only recovery path for a missed keyup is a window blur. Any OS-level interaction that swallows the keyup without blurring the browser window strands the held state indefinitely — every subsequent useKeyHold read returns true until the user physically taps and releases that key again.
Reproduction
- Render anything using
const shift = useKeyHold('Shift'). - On macOS, focus the page and press Cmd+Shift+4 (screenshot-to-selection).
- Press Esc to cancel (or take the shot).
- Observe
useKeyHold('Shift')is now stuck attrue, even though nothing is held.
Other triggers in the same class: Spotlight (Cmd+Space), Mission Control, and various OS shortcuts that consume a modifier keyup while leaving the browser window focused.
Your Minimal, Reproducible Example - (Sandbox Highly Recommended)
https://codesandbox.io/p/sandbox/stoic-fast-h5k2pr
Screenshots or Videos (Optional)
No response
Do you intend to try to help solve this bug with your own PR?
No, because I do not have time to dig into it
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.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the useKeyHold entry point and the global KeyStateTracker behavior, reproducing the issue in the linked CodeSandbox with Cmd+Shift+4 on macOS. Investigate how the tracker handles swallowed keyup events without a window blur; done means useKeyHold('Shift') returns false after the shortcut is canceled or completed without requiring another physical key tap.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- frontend
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 50/100