Activate the pause control on pointerup, not a click that never comes - #155
Merged
Conversation
Clicking pause did nothing on desktop Chrome while P paused fine, so the pause logic was never at fault — the button's activation simply never ran. Instrumenting the live button on production during a failing press gives pointerdown, mousedown, pointerup and mouseup, all on the button, none defaultPrevented, with elementFromPoint at the button's own centre returning the button. Nothing covers it and nothing swallows the events; the browser just declines to synthesize the click that the handler was waiting for. The press vanishes with no feedback, and because pause is a toggle rather than idempotent navigation like the menu buttons, a lost activation is indistinguishable from a dead button. Act on pointerup, the last event actually guaranteed. bindActivation arms on a pointerdown on the same control so a stray pointerup cannot fire it, disarms on pointercancel and pointerleave to keep press-then-drag-away as a cancel, and keeps keyboard activation, which arrives as a click with detail 0. A pointer-driven click is ignored because pointerup already handled it. Verified in a browser across mouse and touch, for an instant click, a 140ms human press and Enter on the focused button: all pause, and a press dragged away does not. Why Chrome withholds the click is still unknown, and is not reproducible here across viewports, HUD scales, fresh and resumed matches, or press durations from 0 to 250ms. This makes the control robust to it rather than explaining it. Closes #153 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BoQrnJcCawJvZ9jGHx5W4P Signed-off-by: Claude <knorcedger@gmail.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What changed?
Clicking the in-match pause button did nothing on desktop Chrome, while
Ppaused fine — so thepause logic was never at fault, the button's activation simply never ran.
Instrumenting the live button on production during a failing press:
All four events land on the button, none is
defaultPrevented, andelementFromPointat thebutton's own centre returns the button — nothing covers it. The browser just never synthesizes the
clickthe handler waits for. The press vanishes with no feedback, and because pause is a togglerather than idempotent navigation like the menu buttons, a lost activation is indistinguishable
from a dead button.
bindActivationnow drives the pause control frompointerup, the last event actually guaranteed:pointerdownon the same control, so a stray pointerup that began elsewhere cannotfire it
pointercancelandpointerleave, keeping press-then-drag-away as a cancelclickwithdetail === 0pointerupalready handled itRelated issue
Closes #153
Why this approach?
Acting on
pointerupfires marginally earlier thanclickand gives up the browser's built-inpress-and-drag-away handling on this one control, which the disarm listeners restore. That is a good
trade for a control that is currently, for at least one player, completely dead.
Why Chrome withholds the click is still unknown. It is not reproducible in headless Chromium
across viewports, HUD scales, fresh vs resumed matches, mouse vs touch, or press durations from
0–250 ms. This makes the control robust to it rather than explaining it — the evidence that
pointeruparrives reliably is what the fix rests on.Verification
Driven in a real browser, mouse and touch, on a running match:
npm run typechecknpm test— 1392 passed, 11 skippednpm run build,npm run bundle:check,npm run bundle:self-testwhen a click follows, keyboard activation, stray pointerup ignored, cancel and leave disarm,
and one press arming only one activation
Provenance and AI assistance
Claude Code (Claude Opus) diagnosed this from console instrumentation supplied by the reporter,
wrote the fix and tests, and ran the browser verification. No generated assets are included.
Contributor checklist
CONTRIBUTING.mdand followed the deterministic simulation rulesgit commit -s)🤖 Generated with Claude Code
https://claude.ai/code/session_01BoQrnJcCawJvZ9jGHx5W4P
Generated by Claude Code