Skip to content

useKeyHold / KeyStateTracker latches a modifier forever when a keyup is swallowed without a blur (e.g. macOS Cmd+Shift+4) #143

Description

@frbarbre

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

  1. Render anything using const shift = useKeyHold('Shift').
  2. On macOS, focus the page and press Cmd+Shift+4 (screenshot-to-selection).
  3. Press Esc to cancel (or take the shot).
  4. Observe useKeyHold('Shift') is now stuck at true, 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions