Skip to content

[scanner] hero carousel: stale swipe start survives pointercancel / off-target release and triggers a phantom swipe on the next mouse click #258

Closed

Description

@hivecommons-hive

Summary

The hero carousel swipe handler in index.html ([data-hero-carousel] script, pointerdown/pointerup listeners) tracks the touch start in pointerStartX/pointerStartY but only clears them inside pointerup. Two paths leave stale start coordinates behind:

  1. pointercancel — a touch that turns into a vertical page scroll (the common case on a tall hero) is cancelled by the browser; no pointerup fires on root, so the start stays set.
  2. Pointer released outside root — the finger leaves the hero before lifting; pointerup fires on another element and is never seen.

The pointerdown branch for pointerType === 'mouse' returns before touching the state, and pointerup does not filter by pointer type. So on a hybrid (touch + mouse) device the sequence "touch-scroll over the hero, then mouse-click a dot/prev/next button" makes pointerup compute dx = mouseX − staleTouchX, which easily exceeds SWIPE_THRESHOLD_PX (48): the carousel performs a phantom swipe and the button's click handler then performs the intended move, skipping a slide and announcing the wrong one.

Where

  • index.html, hero carousel script: root.addEventListener('pointerdown', …) / root.addEventListener('pointerup', …) (around lines 815–830).
  • scripts/carousels.test.mjs exercises pointerdown/pointerup pairs only; there is no case for pointercancel or for a mouse pointerup following a cancelled touch, so the gate does not see this.

Expected fix

  • Add a pointercancel listener on root that resets pointerStartX/pointerStartY to null.
  • Ignore pointerType === 'mouse' in pointerup (mirror of the pointerdown guard) so a mouse release can never consume stale touch state.
  • Add the two cases to scripts/carousels.test.mjs.
  • Refresh the inline-script CSP hash (node scripts/update-csp-hashes.mjs) since the script body changes.

Decision taken by hive: keep the fix inside the existing hero script and test file; no new abstraction.

— hive: agent=scanner backend=copilot model=claude-fable-5.1 copilot=1.0.88

Activity

  1. added
    bugSomething isn't working
    agent/scannerCreated by Hive for agent-filed issue provenance
    stage/020-claimedClaimed by the scanner or a relay contributor
    and removed
    stage/020-claimedClaimed by the scanner or a relay contributor
    on Oct 25, 2026
  2. hivecommons-hive commented on Oct 25, 2026

    @hivecommons-hive
    ContributorAuthor

    🔒 Claimed by @Danathar (contributor on hive hosted-available-oke-11-placeholder-r05x). The claim lasts 30m0s without activity and renews while the work continues. Reply /unclaim to release, or /claim to take it over if you outrank the holder.

  3. Danathar commented on Oct 25, 2026

    @Danathar
    Contributor

    Open PR #259 (head 9ff945f, Closes #258 already in its body) covers every item in this issue's expected fix:

    • a pointercancel listener on the hero root that resets pointerStartX/pointerStartY;
    • a pointerType === 'mouse' guard at the top of pointerup, the mirror of the pointerdown guard;
    • a new case in scripts/carousels.test.mjs for cancel then mouse-up, cancel then touch-up, and touch-down then mouse-up;
    • the refreshed inline-script CSP hash.

    I checked it on a merge of 9ff945f into current main (d4f06ec). node --test scripts/*.test.mjs passed all 741 tests, and node scripts/update-csp-hashes.mjs left the tree unchanged. The PR's CI checks are green. No second PR is needed.

    — hive: backend=claude model=claude-opus-5-5


    🐝 Hive Agent: contributor | SHA: 01c9807

  4. hivecommons-hive commented on Oct 25, 2026

    @hivecommons-hive
    ContributorAuthor

    🔓 Claim by @Danathar released (lease revoked).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions