Conversation
- Created <LottieAnimation /> component with frame-perfect synchronization. - Implemented deterministic rendering by manually driving Lottie frames. - Added support for relative frame contexts in Sequence component. - Updated create-motionforge templates with Lottie examples and dependencies. - Added comprehensive documentation and demo assets. - Bumped motionforge to v1.3.0 and create-motionforge to v1.1.0. Co-authored-by: codedbytahir <200578194+codedbytahir@users.noreply.github.com>
|
👋 Jules, reporting for duty! I'm here to lend a hand with this pull request. When you start a review, I'll add a 👀 emoji to each comment to let you know I've read it. I'll focus on feedback directed at me and will do my best to stay out of conversations between you and other bots or reviewers to keep the noise down. I'll push a commit with your requested changes shortly after. Please note there might be a delay between these steps, but rest assured I'm on the job! For more direct control, you can switch me to Reactive Mode. When this mode is on, I will only act on comments where you specifically mention me with New to Jules? Learn more at jules.google/docs. For security, I will only act on instructions from the user who triggered this task. |
✅ Deploy Preview for motion-forge ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
📝 WalkthroughWalkthroughThis PR introduces Lottie animation support to MotionForge, adding a synchronizable Changes
Sequence Diagram(s)sequenceDiagram
participant App as App/Component
participant LottieAnimation as LottieAnimation
participant LottieWeb as lottie-web
participant MotionForgeTimeline as MotionForge Timeline
App->>LottieAnimation: Render with src, frameStart, frameEnd
activate LottieAnimation
LottieAnimation->>LottieWeb: Initialize Lottie instance on mount
LottieWeb-->>LottieAnimation: DOMLoaded event
LottieAnimation->>LottieAnimation: Set DOMLoaded flag to true
loop On Each Frame
MotionForgeTimeline->>LottieAnimation: useRelativeCurrentFrame / useCurrentFrame
LottieAnimation->>LottieAnimation: Compute currentFrame from relative or absolute context<br/>(apply frameStart, playbackRate, looping logic)
LottieAnimation->>LottieWeb: goToAndStop(lottieFrame, true)
LottieWeb-->>LottieAnimation: Frame updated (no internal playback)
end
App->>LottieAnimation: Unmount
LottieAnimation->>LottieWeb: Remove event listeners & destroy()
deactivate LottieAnimation
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~22 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 3 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
🧪 Generate unit tests (beta)
⚔️ Resolve merge conflicts (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 10
🤖 Fix all issues with AI agents
In `@packages/create-motionforge/templates/hello-world/page.tsx.template`:
- Around line 37-40: The LottieAnimation usage currently points to an external
CDN URL; replace that with a bundled local JSON (e.g., sample-lottie.json) and
update the LottieAnimation src to reference the local asset via an import or
static file path instead of "https://assets10.lottiefiles.com/..."; add the
sample-lottie.json to the template directory so new projects ship with the asset
and update the component usage (LottieAnimation src prop) to load the local
file.
In `@packages/create-motionforge/templates/shared/package.json.template`:
- Line 18: The template pins lottie-web to ^5.12.2 which conflicts with
motionforge@^1.3.0's lottie-web@^5.13.0 requirement; update the lottie-web entry
in the package.json.template from "^5.12.2" to "^5.13.0" (or match motionforge's
range) so both dependencies use the same version range and avoid duplicate
installations.
In `@packages/motionforge/CHANGELOG.md`:
- Line 8: Update the incorrect release date in the CHANGELOG entry header for
version "## [1.3.0]" by replacing "2024-02-25" with the intended release date
"2026-02-15" so the changelog reflects the PR creation/release date; edit the
line that reads '## [1.3.0] - 2024-02-25' to '## [1.3.0] - 2026-02-15'.
In `@packages/motionforge/package.json`:
- Around line 91-93: Update the shared package.json.template to make the
lottie-web dependency match the main package: change the "lottie-web" version
specifier from "^5.12.2" to "^5.13.0" in the create-motionforge CLI template
(the shared package.json.template) so newly scaffolded projects use a compatible
lottie-web range that matches the packages/motionforge package.json.
In `@packages/motionforge/src/components/Sequence.tsx`:
- Around line 110-112: The exported hook useRelativeCurrentFrame now returns
number | null (RelativeFrameContext), which is a breaking change for external
consumers—update the release notes and add a short migration guide showing how
to handle the null case (e.g., using relativeFrame !== null ? relativeFrame :
absoluteFrame, as used in LottieAnimation) and include a minimal example snippet
and suggested fallback strategy; also mention the symbols RelativeFrameContext,
useRelativeCurrentFrame, LottieAnimation, relativeFrame and absoluteFrame so
consumers can find the relevant code, and optionally document or add a helper
alternative hook for callers that want a guaranteed number fallback.
In `@src/lib/remotion/components/Lottie.tsx`:
- Line 34: The isLoaded state is not reset when a new src is initialized,
causing stale true state to let the sync effect call goToAndStop on an unready
animation; inside the initialization useEffect that tears down and recreates the
Lottie animation (the effect that references createAnimation / destroy or the
effect where setIsLoaded(true) is currently set), call setIsLoaded(false) at the
start before creating the new animation so that isLoaded reflects the fresh
instance; ensure this change is applied alongside the existing setIsLoaded(true)
in the animation's load/complete handler so the sync effect (which checks
isLoaded) only runs after the new animation is ready.
- Line 5: The import of useVideoConfig in the Lottie component is unused; remove
useVideoConfig from the import statement that currently reads "import {
useCurrentFrame, useVideoConfig } from '../core/context';" (or alternatively use
it inside the Lottie component if you intended to access video config). Update
the import to only include useCurrentFrame to eliminate the unused-symbol lint
error.
- Around line 94-103: The non-loop branch for computing lottieFrame (variables:
lottieFrame, currentFrame, playbackRate, frameStart, end, duration, loop) only
clamps the upper bound to end and can produce values below frameStart; change
the non-loop logic to clamp lottieFrame between frameStart and end (and
optionally ensure it is not negative by clamping to Math.max(frameStart, 0) if
needed) so the value passed to lottie-web is always within the valid window.
- Line 79: The effect in the Lottie component (useEffect in
src/lib/remotion/components/Lottie.tsx) depends directly on the `src` prop which
can be a new object each render and cause infinite re-initialization; update the
component to stabilize `src` before using it in the dependency array (for
example, compute a stable key with useMemo or a serialized string like
JSON.stringify(src) and use that key in the dependency array) and then use that
stable reference/key in the effect (keep references to the Lottie instance
creation/cleanup in the same effect), or alternatively document that the `src`
prop must be a stable/memoized reference; ensure you only change the dependency
from `[src]` to the new stable memoized value (e.g., `stableSrc` or `srcKey`)
and keep instance teardown/creation logic attached to that stable dependency.
In `@src/lib/remotion/demo/LottieDemo.tsx`:
- Around line 51-61: The Sequence in LottieDemo.tsx is using its default
absolute-fill layout which causes its children to escape the 300px card
container; update the Sequence instance (the one wrapping the LottieAnimation
and Text) to set layout="none" so its content remains positioned inside the
parent div, keeping the existing from/durationInFrames props intact and not
altering the surrounding container styles.
🧹 Nitpick comments (3)
packages/motionforge/src/core/types.ts (1)
62-72: Consider narrowing thesrctype fromobject.
objectaccepts any non-primitive (arrays, dates, regex, etc.). A slightly tighter type likeRecord<string, unknown>would better signal intent and catch accidental misuse, while still accommodating arbitrary Lottie JSON shapes.Suggested change
export interface LottieAnimationProps { - src: string | object; + src: string | Record<string, unknown>;src/lib/remotion/demo/sample-lottie.json (1)
1-35: Duplicate asset: identical topackages/motionforge/src/demo/sample-lottie.json.These two files are byte-for-byte identical. If both packages genuinely need their own copy, consider generating one from the other during build, or placing the asset in a shared location and symlinking/importing from there. This avoids the risk of the files drifting out of sync.
src/lib/remotion/core/types.ts (1)
62-72:src: objectis overly permissive.Consider narrowing the type to
Record<string, unknown>or a dedicatedLottieAnimationDatainterface (e.g., with requiredv,fr,ip,op,layersfields) to catch misuse at compile time.
| <LottieAnimation | ||
| src="https://assets10.lottiefiles.com/packages/lf20_m6cu96.json" | ||
| loop | ||
| /> |
There was a problem hiding this comment.
External URL in a starter template is a reliability risk.
The src points to https://assets10.lottiefiles.com/packages/lf20_m6cu96.json, which is a third-party CDN. If this asset is removed or the CDN is unreachable, new users will see a broken animation on first run — a poor out-of-box experience.
Consider bundling a local sample JSON (similar to the sample-lottie.json already added in this PR for the demo) and referencing it via a static file path or import.
Proposed fix: use a bundled local asset
+import sampleLottie from './sample-lottie.json';
...
<LottieAnimation
- src="https://assets10.lottiefiles.com/packages/lf20_m6cu96.json"
+ src={sampleLottie}
loop
/>You'd also need to include a copy of sample-lottie.json (or similar) in the template directory.
🤖 Prompt for AI Agents
In `@packages/create-motionforge/templates/hello-world/page.tsx.template` around
lines 37 - 40, The LottieAnimation usage currently points to an external CDN
URL; replace that with a bundled local JSON (e.g., sample-lottie.json) and
update the LottieAnimation src to reference the local asset via an import or
static file path instead of "https://assets10.lottiefiles.com/..."; add the
sample-lottie.json to the template directory so new projects ship with the asset
and update the component usage (LottieAnimation src prop) to load the local
file.
| "framer-motion": "^11.13.1", | ||
| "lucide-react": "^0.468.0" | ||
| "lucide-react": "^0.468.0", | ||
| "lottie-web": "^5.12.2" |
There was a problem hiding this comment.
Version mismatch with motionforge's own lottie-web dependency.
The template pins lottie-web at ^5.12.2, but motionforge@^1.3.0 declares a dependency on lottie-web@^5.13.0. This mismatch could cause duplicate installations or resolution conflicts. Align both to the same version range.
🤖 Prompt for AI Agents
In `@packages/create-motionforge/templates/shared/package.json.template` at line
18, The template pins lottie-web to ^5.12.2 which conflicts with
motionforge@^1.3.0's lottie-web@^5.13.0 requirement; update the lottie-web entry
in the package.json.template from "^5.12.2" to "^5.13.0" (or match motionforge's
range) so both dependencies use the same version range and avoid duplicate
installations.
| The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), | ||
| and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). | ||
|
|
||
| ## [1.3.0] - 2024-02-25 |
There was a problem hiding this comment.
Incorrect date: 2024-02-25 should likely be 2026-02-15 (or the intended release date).
The changelog entry date appears to be two years in the past. The PR was created on 2026-02-15.
Proposed fix
-## [1.3.0] - 2024-02-25
+## [1.3.0] - 2026-02-15📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| ## [1.3.0] - 2024-02-25 | |
| ## [1.3.0] - 2026-02-15 |
🤖 Prompt for AI Agents
In `@packages/motionforge/CHANGELOG.md` at line 8, Update the incorrect release
date in the CHANGELOG entry header for version "## [1.3.0]" by replacing
"2024-02-25" with the intended release date "2026-02-15" so the changelog
reflects the PR creation/release date; edit the line that reads '## [1.3.0] -
2024-02-25' to '## [1.3.0] - 2026-02-15'.
| "dependencies": { | ||
| "lottie-web": "^5.13.0" | ||
| } |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
# Check the motionforge package.json dependencies
cat -n packages/motionforge/package.json | grep -A 5 -B 5 "lottie-web"Repository: codedbytahir/motionforge
Length of output: 272
🏁 Script executed:
# Check the CLI template for lottie-web version
cat -n shared/package.json.template | grep -A 5 -B 5 "lottie-web"Repository: codedbytahir/motionforge
Length of output: 128
🏁 Script executed:
# Find if lottie-web or LottieAnimation is used in the codebase
rg -i "lottie" --type ts --type tsx --type js --type jsxRepository: codedbytahir/motionforge
Length of output: 95
🌐 Web query:
latest version of lottie-web npm package 2025
💡 Result:
The latest lottie-web version on npm released in 2025 is 5.13.0 (it’s also the current latest tag), published ~4 months ago (≈ Oct 2025). [1]
Source: npm package page for lottie-web@5.13.0. [1]
References:
[1] (npmjs.com)
Citations:
🏁 Script executed:
# Search for lottie-web usage without type restrictions
rg "lottie-web" -A 3 -B 1Repository: codedbytahir/motionforge
Length of output: 3841
🏁 Script executed:
# Search for lottie or LottieAnimation more broadly
rg "lottie" -i -A 2 -B 1Repository: codedbytahir/motionforge
Length of output: 22590
🏁 Script executed:
# Find if there's a template file with a different name/path
fd "package.*template" -type fRepository: codedbytahir/motionforge
Length of output: 238
🏁 Script executed:
# List files in shared directory to see what exists
ls -la shared/ 2>/dev/null || echo "shared directory not found"Repository: codedbytahir/motionforge
Length of output: 94
Update the CLI template to use lottie-web ^5.13.0 to match the main package.
The template at packages/create-motionforge/templates/shared/package.json.template specifies lottie-web ^5.12.2, but packages/motionforge/package.json requires ^5.13.0. These versions don't overlap (^5.12.2 is >=5.12.2 <5.13.0, while ^5.13.0 is >=5.13.0 <5.14.0), which can cause version conflicts when users scaffold a project with the template and install motionforge. Update the template to ^5.13.0.
Regarding the optional dependency suggestion: LottieAnimation is a core, directly-exported component with a top-level import of lottie-web. Making it optional would require dynamic imports and error handling throughout the codebase, which is a significant refactor. Since LottieAnimation is a first-class feature (not a conditional enhancement), keeping it as a hard dependency is reasonable.
🤖 Prompt for AI Agents
In `@packages/motionforge/package.json` around lines 91 - 93, Update the shared
package.json.template to make the lottie-web dependency match the main package:
change the "lottie-web" version specifier from "^5.12.2" to "^5.13.0" in the
create-motionforge CLI template (the shared package.json.template) so newly
scaffolded projects use a compatible lottie-web range that matches the
packages/motionforge package.json.
| const RelativeFrameContext = createContext<number | null>(null); | ||
|
|
||
| export const useRelativeCurrentFrame = () => useContext(RelativeFrameContext); |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
# First, let's examine the Sequence.tsx file around the lines mentioned
cat -n packages/motionforge/src/components/Sequence.tsx | sed -n '100,125p'Repository: codedbytahir/motionforge
Length of output: 946
🏁 Script executed:
# Search for all usages of useRelativeCurrentFrame
rg -n 'useRelativeCurrentFrame' --type=ts --type=tsx -B2 -A4Repository: codedbytahir/motionforge
Length of output: 95
🏁 Script executed:
# Also search in JS/JSX files in case there are any
find . -type f \( -name "*.ts" -o -name "*.tsx" -o -name "*.js" -o -name "*.jsx" \) | xargs grep -l 'useRelativeCurrentFrame' 2>/dev/null | head -20Repository: codedbytahir/motionforge
Length of output: 391
🏁 Script executed:
# Check the Lottie.tsx file where useRelativeCurrentFrame is likely used
cat -n packages/motionforge/src/components/Lottie.tsxRepository: codedbytahir/motionforge
Length of output: 4820
🏁 Script executed:
# Check the index.ts files to see how it's exported
cat -n packages/motionforge/src/index.tsRepository: codedbytahir/motionforge
Length of output: 5664
🏁 Script executed:
# Get more detailed context around usages
rg 'useRelativeCurrentFrame' --type-add 'tsx:*.tsx' --type-add 'ts:*.ts' -B3 -A3 packages/motionforge/src/ 2>/dev/null || rg 'useRelativeCurrentFrame' -B3 -A3 packages/motionforge/src/Repository: codedbytahir/motionforge
Length of output: 2347
🏁 Script executed:
# Check if there are other usages in the src/lib/remotion directories
cat -n src/lib/remotion/components/Lottie.tsx 2>/dev/null | head -50Repository: codedbytahir/motionforge
Length of output: 2005
🏁 Script executed:
# Check the other Sequence file
cat -n src/lib/remotion/components/Sequence.tsx 2>/dev/null | head -50Repository: codedbytahir/motionforge
Length of output: 1667
🏁 Script executed:
# Search for any other usages in the entire src directory
rg 'useRelativeCurrentFrame' src/ 2>/dev/null || find src -type f \( -name "*.ts" -o -name "*.tsx" -o -name "*.js" -o -name "*.jsx" \) -exec grep -l 'useRelativeCurrentFrame' {} \;Repository: codedbytahir/motionforge
Length of output: 423
useRelativeCurrentFrame type change properly handled internally.
The type change from number to number | null is a breaking change for external consumers, but internal usage in LottieAnimation correctly handles it with a null check: relativeFrame !== null ? relativeFrame : absoluteFrame. However, external consumers of this exported hook may not handle the null case—document this change in release notes and consider providing a migration guide.
🤖 Prompt for AI Agents
In `@packages/motionforge/src/components/Sequence.tsx` around lines 110 - 112, The
exported hook useRelativeCurrentFrame now returns number | null
(RelativeFrameContext), which is a breaking change for external consumers—update
the release notes and add a short migration guide showing how to handle the null
case (e.g., using relativeFrame !== null ? relativeFrame : absoluteFrame, as
used in LottieAnimation) and include a minimal example snippet and suggested
fallback strategy; also mention the symbols RelativeFrameContext,
useRelativeCurrentFrame, LottieAnimation, relativeFrame and absoluteFrame so
consumers can find the relevant code, and optionally document or add a helper
alternative hook for callers that want a guaranteed number fallback.
|
|
||
| import React, { useEffect, useRef, useState } from 'react'; | ||
| import lottie, { AnimationItem, AnimationConfigWithData, AnimationConfigWithPath } from 'lottie-web'; | ||
| import { useCurrentFrame, useVideoConfig } from '../core/context'; |
There was a problem hiding this comment.
Unused import: useVideoConfig.
useVideoConfig is imported but never referenced in this component.
Proposed fix
-import { useCurrentFrame, useVideoConfig } from '../core/context';
+import { useCurrentFrame } from '../core/context';📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| import { useCurrentFrame, useVideoConfig } from '../core/context'; | |
| import { useCurrentFrame } from '../core/context'; |
🤖 Prompt for AI Agents
In `@src/lib/remotion/components/Lottie.tsx` at line 5, The import of
useVideoConfig in the Lottie component is unused; remove useVideoConfig from the
import statement that currently reads "import { useCurrentFrame, useVideoConfig
} from '../core/context';" (or alternatively use it inside the Lottie component
if you intended to access video config). Update the import to only include
useCurrentFrame to eliminate the unused-symbol lint error.
| const absoluteFrame = useCurrentFrame(); | ||
| const currentFrame = relativeFrame !== null ? relativeFrame : absoluteFrame; | ||
|
|
||
| const [isLoaded, setIsLoaded] = useState(false); |
There was a problem hiding this comment.
isLoaded is not reset when src changes — stale state bug.
When src changes, the initialization effect (Line 37) destroys the old animation and creates a new one, but isLoaded remains true from the previous instance. On the next frame change, the sync effect (Line 82) will call goToAndStop on a not-yet-loaded animation because it still sees isLoaded === true.
Reset isLoaded at the start of the initialization effect.
Proposed fix
// Initialize Lottie instance
useEffect(() => {
if (!containerRef.current) return;
+ setIsLoaded(false);
// Clear container to prevent duplicate renders
containerRef.current.innerHTML = '';Also applies to: 67-68, 79-79
🤖 Prompt for AI Agents
In `@src/lib/remotion/components/Lottie.tsx` at line 34, The isLoaded state is not
reset when a new src is initialized, causing stale true state to let the sync
effect call goToAndStop on an unready animation; inside the initialization
useEffect that tears down and recreates the Lottie animation (the effect that
references createAnimation / destroy or the effect where setIsLoaded(true) is
currently set), call setIsLoaded(false) at the start before creating the new
animation so that isLoaded reflects the fresh instance; ensure this change is
applied alongside the existing setIsLoaded(true) in the animation's
load/complete handler so the sync effect (which checks isLoaded) only runs after
the new animation is ready.
| anim.destroy(); | ||
| animationRef.current = null; | ||
| }; | ||
| }, [src]); |
There was a problem hiding this comment.
Object src as a useEffect dependency will cause infinite re-initialization.
When a consumer passes an inline object literal (e.g., <LottieAnimation src={{ ...data }} />), a new reference is created on every render, causing the [src] dependency to trigger the effect repeatedly — destroying and re-creating the Lottie instance each frame.
Consider accepting a stable reference via useMemo internally, or document that callers must memoize src. A common pattern is to serialize and compare:
Proposed fix — stabilize with useMemo
+import React, { useEffect, useMemo, useRef, useState } from 'react';
...
+ // Stabilize object src to avoid re-init on every render
+ const stableSrc = useMemo(
+ () => (typeof src === 'object' ? JSON.parse(JSON.stringify(src)) : src),
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ [typeof src === 'string' ? src : JSON.stringify(src)]
+ );
+
useEffect(() => {
...
- }, [src]);
+ }, [stableSrc]);Alternatively, document that src must be a stable reference (module import or memoized value).
🤖 Prompt for AI Agents
In `@src/lib/remotion/components/Lottie.tsx` at line 79, The effect in the Lottie
component (useEffect in src/lib/remotion/components/Lottie.tsx) depends directly
on the `src` prop which can be a new object each render and cause infinite
re-initialization; update the component to stabilize `src` before using it in
the dependency array (for example, compute a stable key with useMemo or a
serialized string like JSON.stringify(src) and use that key in the dependency
array) and then use that stable reference/key in the effect (keep references to
the Lottie instance creation/cleanup in the same effect), or alternatively
document that the `src` prop must be a stable/memoized reference; ensure you
only change the dependency from `[src]` to the new stable memoized value (e.g.,
`stableSrc` or `srcKey`) and keep instance teardown/creation logic attached to
that stable dependency.
| // Calculate the target frame in the Lottie animation | ||
| let lottieFrame = (currentFrame * playbackRate) + frameStart; | ||
|
|
||
| if (loop && duration > 0) { | ||
| // Loop within the specified window [frameStart, end] | ||
| lottieFrame = frameStart + ((lottieFrame - frameStart) % duration); | ||
| } else { | ||
| // Clamp to the end frame if not looping | ||
| lottieFrame = Math.min(lottieFrame, end); | ||
| } |
There was a problem hiding this comment.
Missing lower-bound clamp — lottieFrame can go below frameStart.
In the non-loop branch (Line 102), lottieFrame is clamped to end but never to frameStart. If currentFrame is 0 and playbackRate is 1, the result is frameStart (correct). But with unusual values (e.g., negative currentFrame from a sequence edge, or playbackRate < 0), lottieFrame can fall below frameStart or even below 0, which would be out of bounds for lottie-web.
Proposed fix
} else {
// Clamp to the end frame if not looping
- lottieFrame = Math.min(lottieFrame, end);
+ lottieFrame = Math.max(frameStart, Math.min(lottieFrame, end));
}
+
+ // Ensure we never go below 0
+ lottieFrame = Math.max(0, lottieFrame);📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| // Calculate the target frame in the Lottie animation | |
| let lottieFrame = (currentFrame * playbackRate) + frameStart; | |
| if (loop && duration > 0) { | |
| // Loop within the specified window [frameStart, end] | |
| lottieFrame = frameStart + ((lottieFrame - frameStart) % duration); | |
| } else { | |
| // Clamp to the end frame if not looping | |
| lottieFrame = Math.min(lottieFrame, end); | |
| } | |
| // Calculate the target frame in the Lottie animation | |
| let lottieFrame = (currentFrame * playbackRate) + frameStart; | |
| if (loop && duration > 0) { | |
| // Loop within the specified window [frameStart, end] | |
| lottieFrame = frameStart + ((lottieFrame - frameStart) % duration); | |
| } else { | |
| // Clamp to the end frame if not looping | |
| lottieFrame = Math.max(frameStart, Math.min(lottieFrame, end)); | |
| } | |
| // Ensure we never go below 0 | |
| lottieFrame = Math.max(0, lottieFrame); |
🤖 Prompt for AI Agents
In `@src/lib/remotion/components/Lottie.tsx` around lines 94 - 103, The non-loop
branch for computing lottieFrame (variables: lottieFrame, currentFrame,
playbackRate, frameStart, end, duration, loop) only clamps the upper bound to
end and can produce values below frameStart; change the non-loop logic to clamp
lottieFrame between frameStart and end (and optionally ensure it is not negative
by clamping to Math.max(frameStart, 0) if needed) so the value passed to
lottie-web is always within the valid window.
| <div style={{ width: 300, textAlign: 'center' }}> | ||
| <Sequence from={60} durationInFrames={120}> | ||
| <div style={{ height: 200, background: '#1e293b', borderRadius: 12, overflow: 'hidden', marginBottom: 10 }}> | ||
| <LottieAnimation | ||
| src={sampleLottie} | ||
| loop | ||
| /> | ||
| </div> | ||
| <Text style={{ fontSize: 16 }}>Inside Sequence (Starts at frame 60)</Text> | ||
| </Sequence> | ||
| </div> |
There was a problem hiding this comment.
Layout bug: Sequence's default absolute-fill layout breaks the card container.
The Sequence component defaults to layout='absolute-fill' (see Sequence.tsx Line 73: position: 'absolute'). This means the content inside the Sequence will escape the width: 300 parent div and fill the nearest positioned ancestor — the root AbsoluteFill — overlaying the entire viewport instead of staying inside the card.
The other three demo blocks work correctly because they don't use Sequence.
Proposed fix: use `layout="none"` on the Sequence
- <div style={{ width: 300, textAlign: 'center' }}>
- <Sequence from={60} durationInFrames={120}>
+ <div style={{ width: 300, textAlign: 'center', position: 'relative' }}>
+ <Sequence from={60} durationInFrames={120} layout="none">📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| <div style={{ width: 300, textAlign: 'center' }}> | |
| <Sequence from={60} durationInFrames={120}> | |
| <div style={{ height: 200, background: '#1e293b', borderRadius: 12, overflow: 'hidden', marginBottom: 10 }}> | |
| <LottieAnimation | |
| src={sampleLottie} | |
| loop | |
| /> | |
| </div> | |
| <Text style={{ fontSize: 16 }}>Inside Sequence (Starts at frame 60)</Text> | |
| </Sequence> | |
| </div> | |
| <div style={{ width: 300, textAlign: 'center', position: 'relative' }}> | |
| <Sequence from={60} durationInFrames={120} layout="none"> | |
| <div style={{ height: 200, background: '#1e293b', borderRadius: 12, overflow: 'hidden', marginBottom: 10 }}> | |
| <LottieAnimation | |
| src={sampleLottie} | |
| loop | |
| /> | |
| </div> | |
| <Text style={{ fontSize: 16 }}>Inside Sequence (Starts at frame 60)</Text> | |
| </Sequence> | |
| </div> |
🤖 Prompt for AI Agents
In `@src/lib/remotion/demo/LottieDemo.tsx` around lines 51 - 61, The Sequence in
LottieDemo.tsx is using its default absolute-fill layout which causes its
children to escape the 300px card container; update the Sequence instance (the
one wrapping the LottieAnimation and Text) to set layout="none" so its content
remains positioned inside the parent div, keeping the existing
from/durationInFrames props intact and not altering the surrounding container
styles.
This PR introduces a robust Lottie animation system to MotionForge, comparable to Remotion's implementation.
Key features:
LottieAnimationcomponent disables internalrequestAnimationFrameand instead seeks to specific frames based on the MotionForge timeline.frameStart,frameEnd,playbackRate, andloopproperties.Sequenceand uses relative frame numbers for synchronization.create-motionforgenow includelottie-weband a working example.A new demo has been added to showcase these capabilities.
PR created automatically by Jules for task 8781275110360285891 started by @codedbytahir
Summary by CodeRabbit
Release Notes