Repository navigation
@remotion/gsap: Fix delayed fromTo leaving from-values behind on remount - #12180
Merged
Merged
Conversation
…remount useGsapTimeline() primed the timeline inside its gsap.context(). Seeking a fromTo with immediateRender: false makes GSAP create the tween's start state lazily, so the context recorded it. context.revert() then undid the start state before its owner, and the owner's revert put the from-values back on the element. The next mount on the same element (Strict Mode, a dependency rebuild) read them as the element's own style. Prime outside the context so each tween reverts its own start state.
Contributor
Contributor
There was a problem hiding this comment.
✅ No new issues found.
Reviewed changes
packages/gsap/src/use-gsap-timeline.ts— Closes thecontext.add()callback afterstate.controls.pause()and runs the initial playhead sweep outside the context. The_startAttween that GSAP lazily creates for afromTo/fromwithimmediateRender: falseis no longer captured bycontext.revert(), so it is no longer reverted ahead of its owning tween. The owner reverts its own start state, which restores the element's React style rather than leaving the from-values behind on the element for the next mount.packages/gsap/src/test/use-gsap-timeline.test.tsx— Adds two regression tests (Strict Mode setup-cleanup-setup, and a rebuild fromdependencies) asserting the element's ownopacity: 0.25survives a delayedfromTo. I confirmed both fail against32af7e8fand pass with this change.
deepseek-v4.1-flash | 𝕏
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.

useGsapTimeline()primed the timeline inside itsgsap.context(). Seeking afromTowithimmediateRender: falsemakes GSAP create that tween's start state lazily, so the context recorded it. On cleanup,context.revert()undid the start state first, then the owning tween, whose revert puts its from-values back on the element. Nothing removes them after that. The next mount on the same element (Strict Mode, or a rebuild fromdependencies) reads them as the element's own style.What it looked like for us: an end title animated with
sat 60% lower in the Player, cut off by its
overflow: hiddenmask (transform: translate(0px, 66px)at the end of the timeline), and the offset compounded with every remount. Exports were fine since nothing remounts there.The fix primes and seeks outside the context. The context still records everything the builder creates, and each tween reverts its own start state in the right order.
Minimal repro with GSAP 3.15.0 alone, no React:
timeline.revert()restores it correctly, as does afromTowith the defaultimmediateRenderor afrom()withimmediateRender: false. Happy to report the context ordering to GreenSock too if that's useful.Testing:
packages/gsap: a Strict Mode mount, and a rebuild fromdependencies. Both fail onmain(opacity 0.2, the from-value, instead of the element's 0.25) and pass with the fix.bun test src/test: 48 pass.tsgoclean, lint unchanged.