Skip to content

Activate the pause control on pointerup, not a click that never comes - #155

Merged
Knorcedger merged 1 commit into
mainfrom
claude/pause-menu-autosave-33m17i
Aug 23, 2026
Merged

Activate the pause control on pointerup, not a click that never comes#155
Knorcedger merged 1 commit into
mainfrom
claude/pause-menu-autosave-33m17i

Conversation

@Knorcedger

Copy link
Copy Markdown
Owner

What changed?

Clicking the in-match pause button 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:

COVER CHECK {onTop: 'BUTTON.bf-btn', isTheButton: true}
1. pointerdown mouse prevented=false
2. mousedown         prevented=false
3. pointerup   mouse prevented=false
4. mouseup           prevented=false

All four events land on the button, none is defaultPrevented, and elementFromPoint at the
button's own centre returns the button — nothing covers it. The browser just never synthesizes the
click the handler waits 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.

bindActivation now drives the pause control from pointerup, the last event actually guaranteed:

  • arms on a pointerdown on the same control, so a stray pointerup that began elsewhere cannot
    fire it
  • disarms on pointercancel and pointerleave, keeping press-then-drag-away as a cancel
  • keeps keyboard activation — Enter/Space arrive as a click with detail === 0
  • ignores a pointer-driven click, since pointerup already handled it

Related issue

Closes #153

Why this approach?

Acting on pointerup fires marginally earlier than click and gives up the browser's built-in
press-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
pointerup arrives reliably is what the fix rests on.

Verification

Driven in a real browser, mouse and touch, on a running match:

Input Result
Instant click pauses
Held 140 ms (a human press) pauses
Enter on the focused button pauses
Press then drag away does not pause
  • npm run typecheck
  • npm test — 1392 passed, 11 skipped
  • npm run build, npm run bundle:check, npm run bundle:self-test
  • I added or updated tests where behavior changed — pointerup activation, no double-activation
    when a click follows, keyboard activation, stray pointerup ignored, cancel and leave disarm,
    and one press arming only one activation
  • I included screenshots or a recording for visible changes — the table above is the evidence

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

  • I searched issues and active pull requests before implementation and coordinated ownership in the linked issue
  • This pull request closes or references exactly one primary coordination issue
  • I read CONTRIBUTING.md and followed the deterministic simulation rules
  • I reviewed and understand every submitted change
  • I have the right to submit this code and any included assets
  • My commits are signed off under the Developer Certificate of Origin (git commit -s)
  • This PR contains no credentials, private player data, or unlicensed third-party material

🤖 Generated with Claude Code

https://claude.ai/code/session_01BoQrnJcCawJvZ9jGHx5W4P


Generated by Claude Code

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>
@vercel

vercel Bot commented Aug 23, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
bannerfall Ready Ready Preview Aug 23, 2026 9:28am

Request Review

@Knorcedger
Knorcedger merged commit 8635da0 into main Aug 23, 2026
3 checks passed
@Knorcedger
Knorcedger deleted the claude/pause-menu-autosave-33m17i branch August 23, 2026 09:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Pause button silently dead: the browser delivers pointerup but never synthesizes a click

1 participant