Skip to content

fix(interactions): measure by hand when the scroll timeline's scroller cannot scroll - #134

Merged
Gamote merged 1 commit into
mainfrom
fix/scroll-scrub-non-scrolling-scroller
Aug 16, 2026
Merged

fix(interactions): measure by hand when the scroll timeline's scroller cannot scroll#134
Gamote merged 1 commit into
mainfrom
fix/scroll-scrub-non-scrolling-scroller

Conversation

@Gamote

@Gamote Gamote commented Aug 16, 2026

Copy link
Copy Markdown
Owner

What

lottieScrollScrub drives the playhead from a ViewTimeline on the animation's root. A view timeline binds to the nearest ancestor that is a scroll container, and any non-visible overflow makes an element one whether or not it ever scrolls. With overflow-x: hidden on html, body (a common rule, and create-next-app's default stylesheet), body becomes the timeline's scroller while the viewport is what moves: the timeline stays active at one position and a page scrub stands still, with no warning.

The scrub now trusts the timeline only when its scroller is the document's own (document.scrollingElement) or can scroll along the chosen axis, decided once per visibility entry so the platform path stays free of layout reads; otherwise it measures the root against the viewport by hand, the same arithmetic the timeline would have produced. A scrolling div is unaffected.

Verified

  • Four new tests, written red-first (the two non-scrolling-scroller cases fail on main): a non-scrolling scroller falls back to geometry with no warning; a real scroller keeps the timeline; the check reruns on each entry; the inline axis checks inline extents. The ViewTimeline test stub gains source and setSource.
  • pnpm check green: 478 tests, coverage 100 / 97.43 / 100 / 100, budgets under, 34 pages rendered.
  • Real browser (Playwright, Chromium), the packed build installed into a Next.js 16 Turbopack app with html, body { overflow-x: hidden }: a page scrub that sat at one frame on 3.0.0 now runs 0 → 180 linearly across the root's journey, on both the component path (tall <Lottie> root, sticky <LottieDisplay>) and the hook path (setRootRef on a section). Without the rule, behaviour is identical to before.

…r cannot scroll

A view timeline binds to the nearest ancestor that is a scroll container,
and any non-visible overflow makes an element one whether or not it ever
scrolls. With `overflow-x: hidden` on `html, body`, `body` becomes the
timeline's scroller while the viewport is what moves, so the timeline stays
active at one position and the scrub stands still.

The scrub now trusts the timeline only when its scroller is the document's
own or can scroll along the chosen axis, decided once per visibility entry;
otherwise it measures the root against the viewport by hand, which is the
arithmetic the timeline would have produced. The test stub gains a `source`
so both paths are pinned.
@codecov

codecov Bot commented Aug 16, 2026

Copy link
Copy Markdown

Welcome to Codecov 🎉

Once you merge this PR into your default branch, you're all set! Codecov will compare coverage reports and display results in all future pull requests.

Thanks for integrating Codecov - We've got you covered ☂️

@Gamote
Gamote merged commit f44617b into main Aug 16, 2026
6 checks passed
@Gamote
Gamote deleted the fix/scroll-scrub-non-scrolling-scroller branch August 16, 2026 13:34
@Gamote Gamote mentioned this pull request Aug 16, 2026
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.

1 participant