Stop the project gallery seizing up on a phone - #9
Merged
Merged
Conversation
Three things could hold the gallery still with nothing left to let it go again, and all three are reachable with a finger. The worst is the hold that keeps the strip still under a resting pointer. A finger cannot rest on anything, and `pointerleave` after a touch is not something every browser sends — so on a phone the hold went on and nothing lifted it. It is now asked for only where hovering is a thing the device does, and a cancelled gesture lifts it as well, since a browser taking a pan over is the moment a leave is most likely to go missing. A tap also leaves the card it landed on holding the focus, and a press now says that whoever is pressing is not the keyboard visitor the focus hold was put there for. A drag whose pointer capture is lost some other way is let go of through `lostpointercapture`, which is the one event that always arrives. The wait before the drift resumes is back to 1200ms, and it is now measured from the strip moving rather than from wheel and touch events. Watching the position covers every way it can be moved, the momentum that outlives a finger among them, and needs nothing to tell it the visitor has finished: it reads the last movement, so it always runs out. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015aCGjKwtBpk8NdVKxQiCRA
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
This branch was successfully deployed
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.
Follow-up to #8, which merged before this landed. The gallery could stop drifting on a phone and never start again.
What was wrong
Three things could hold the drift still with nothing left to let it go again, and all three are reachable with a finger but not with a mouse — which is why the desktop testing on #8 missed them.
The hover hold, most likely the one being hit. A finger cannot rest on anything, and
pointerleaveafter a touch is not something every browser sends — a browser taking a pan over is exactly when it goes missing. If it never arrived, the hold went on and nothing could lift it: a later swipe only sets it again. It is now asked for only where hovering is a thing the device does, ignores touch-typed pointers, and is lifted by a cancelled gesture too.The focus hold. A tap leaves the card it landed on holding the focus.
:focus-visibleshould be false there, but if a browser disagrees the strip is stopped for good. A press now clears the hold outright — whoever is pressing is not the keyboard visitor it was put there for.A drag that loses its pointer. If
pointerupnever arrived the drag was never let go of.lostpointercaptureis the one event that always turns up, and it now ends the drag as well.What else changed
The wait before the drift resumes is back to 1200ms, and it is measured from the strip moving rather than from wheel and touch events. Watching the position covers every way the strip can be moved — a trackpad, a swipe, the momentum that outlives the finger, a card being scrolled into view — and needs nothing to tell it the visitor has finished, so it always runs out. The
wheelandtouchmovelisteners are gone with it.Honesty about the diagnosis
I could not reproduce the stall itself: synthetic touch in Chromium recovered even on the merged code. What is here is the result of instrumenting the component and driving real touch events through CDP to find every path that can hold the drift permanently, then closing all of them. So this is not "found the line and fixed it" — it is "removed the class of bug the report points at".
The testing on #8 also claimed more than it had earned for touch: it drove the strip with
scrollByfrom script, which produces no touch events at all. The runs below use real touch.Testing
Mobile emulation, real touch through CDP, against a production build.
pointerenterwhosepointerleavenever arrivespointerentertypedmouseon a device that cannot hoverDesktop is unregressed: 40.0 px/s, hover holds indefinitely and releases on leave, drag both ways, a drag over a card does not navigate, a plain click does, a tab-focused card holds it, reduced motion stops it, no console errors.
One number moved on purpose: tabbing off the strip now waits 1200ms before drifting, where it used to resume at once. Tabbing scrolls the strip, and that is the visitor scrolling it — the old wheel and touch listeners simply could not see it.
typecheckandbuildpass.lintreports the same 41 problems with and without this change, all pre-existing, inapp.vueandabout.vue.Generated by Claude Code