Skip to content

feat: add initial motion.dev support for Lynx#1062

Merged
colinaaa merged 51 commits intolynx-family:mainfrom
f0rdream:motion_lynx
Jan 29, 2026
Merged

feat: add initial motion.dev support for Lynx#1062
colinaaa merged 51 commits intolynx-family:mainfrom
f0rdream:motion_lynx

Conversation

@f0rdream
Copy link
Copy Markdown
Collaborator

@f0rdream f0rdream commented Jun 10, 2025

Summary

Add initial support for motion in Lynx #1935

Checklist

  • Tests updated (or not required).
  • Documentation updated (or not required).

Summary by CodeRabbit

  • New Features
    • Added @lynx-js/motion package with comprehensive animation capabilities including spring, keyframe, and decay animations
    • Introduced MotionValue system for managing animation state
    • Added Motion Mini variant for performance-optimized animations
    • Included extensive easing functions and interactive animation examples

✏️ Tip: You can customize this high-level summary in your review settings.

@f0rdream f0rdream requested a review from colinaaa as a code owner June 10, 2025 13:29
@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented Jun 10, 2025

🦋 Changeset detected

Latest commit: 5a6a2b2

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@lynx-js/motion Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@f0rdream f0rdream changed the title feat: add initial motion.dev support for Lynx WIP: feat: add initial motion.dev support for Lynx Jun 10, 2025
@Dugyu Dugyu self-requested a review August 6, 2025 06:39
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Nov 13, 2025

📝 Walkthrough

Walkthrough

Introduces a comprehensive motion and animation library for Lynx (@lynx-js/motion) with core animation APIs, a Motion Mini variant for lightweight numeric animations, extensive example components demonstrating animation patterns, polyfills for DOM-like style utilities, complete type definitions, and a full test suite alongside configuration and build setup.

Changes

Cohort / File(s) Summary
Core Animation Library
packages/motion/src/animation/index.ts, packages/motion/src/animation/...
Comprehensive animation API exposing animate, stagger, motionValue, spring, springValue, mix, progress, mapValue, clamp, transformValue, styleEffect; delegates to framer-motion and motion-dom with main-thread context wrapping.
Motion Mini Variant
packages/motion/src/mini/core/*.ts, packages/motion/src/mini/index.ts
Lightweight numeric-focused animation system with MotionValue abstraction, animate for spring/tween animations, 11 easing functions, and state tracking.
DOM & Polyfills
packages/motion/src/polyfill/*.ts, packages/motion/src/types/index.ts
ElementCompt wrapper providing DOM-like style utilities (getComputedStyle, style proxy, getBoundingClientRect); global shims for queueMicrotask and minimal DOM API; utility functions for selector/element conversion.
Hooks & Utilities
packages/motion/src/hooks/*.ts, packages/motion/src/utils/*.ts
Main-thread hooks (useMotionValueRef, useMotionValueRefEvent) and utilities (registered function registry, element guards, noop helpers).
Type Definitions & Environment
packages/motion/src/env_types/papi.d.ts
PAPI bindings declaring ElementNode, global functions for element/attribute/style manipulation, AnimationOperation enum, and __ElementAnimate for animation control.
Example Components
examples/motion/src/{Basic,BasicPercent,ColorInterception,Spring,Stagger,Text,BasicSelector,MotionValue,iOSSlider,Mini}/*.tsx
10 example components demonstrating various animation patterns (scale, color, stagger, text, spring, iOS slider) with supporting styles.
Example App & Config
examples/motion/src/{index.tsx,App.tsx,App.css}, examples/motion/lynx.config.js, examples/motion/package.json, examples/motion/tsconfig.json
Motion examples entry point, app switcher component, build configuration with QR code and React plugins, build scripts, and TypeScript setup.
Test Suite
packages/motion/__tests__/*.tsx
Comprehensive tests covering MotionValue, animate, easings, hooks, element polyfill, utilities, spring integration, and wrapper animation APIs; includes mock main/background thread harness.
Build & Configuration
packages/motion/{rslib.config.ts,tsconfig.{json,build.json},vitest.config.ts,turbo.jsonc,package.json}, .changeset/moody-baboons-happen.md
Motion package build configuration (ESM, dts generation), TypeScript project references, Vitest integration, Turbo build task definition, and changeset entry.
Root Configuration Updates
tsconfig.json, pnpm-workspace.yaml, vitest.config.ts, biome.jsonc, eslint.config.js
Added motion package to workspace, TypeScript references, Vitest projects list, and linter ignores for motion tests.
Package Metadata & Licensing
packages/motion/{package.json,README.md,LICENSE,NOTICE}
Package manifest with exports map (default/mini entry points), README with feature documentation and CLI reference, Apache 2.0 license, and third-party attribution (framer-motion, motion-dom, motion-utils).
Related Build Dependencies
packages/lynx/gesture-runtime/turbo.jsonc
Updated build task dependency from @lynx-js/react#build to ^build for correct Turbo build graph ordering.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Possibly related issues

  • [Feature] Support motion in Lynx #1935 — This PR directly implements the motion/animation support features (animate, stagger, MotionValue, element polyfills, and interactive examples) requested in the feature issue.

Possibly related PRs

Suggested reviewers

  • Huxpro
  • hzy
  • colinaaa

Poem

🐰 Hoppy hops with frames that flow,
Motion values steal the show—
Stagger, spring, and colors bright,
Animations dance with pure delight!
From iOS sliders to the text,
What bounces next? 🎬✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 6.74% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title 'feat: add initial motion.dev support for Lynx' accurately describes the primary change: introducing motion.dev animation library support to the Lynx framework, as evidenced by the comprehensive addition of motion package files, examples, and configurations.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@f0rdream f0rdream force-pushed the motion_lynx branch 2 times, most recently from 8655395 to 39e92d5 Compare November 13, 2025 10:35
@f0rdream f0rdream changed the title WIP: feat: add initial motion.dev support for Lynx feat: add initial motion.dev support for Lynx Nov 13, 2025
@codecov
Copy link
Copy Markdown

codecov Bot commented Nov 13, 2025

Codecov Report

❌ Patch coverage is 95.53429% with 28 lines in your changes missing coverage. Please review.
✅ All tests successful. No failed tests found.

Files with missing lines Patch % Lines
packages/motion/src/mini/core/easings.ts 80.70% 11 Missing ⚠️
packages/motion/src/polyfill/shim.ts 84.00% 8 Missing ⚠️
packages/motion/src/polyfill/element.ts 96.47% 5 Missing ⚠️
packages/motion/src/animation/index.ts 97.67% 2 Missing ⚠️
packages/motion/src/hooks/useMotionValueRef.ts 94.73% 1 Missing ⚠️
packages/motion/src/types/index.ts 50.00% 1 Missing ⚠️

📢 Thoughts on this report? Let us know!

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 20

♻️ Duplicate comments (3)
examples/motion/src/Spring/styles.css (1)

1-6: Duplicate styling pattern across examples.

This .case-container class is identical to those in other motion example stylesheets. See comment on examples/motion/src/ColorInterception/styles.css for the refactoring suggestion.

examples/motion/src/Text/styles.css (1)

1-6: Duplicate .case-container definition.

This is the same .case-container pattern duplicated from other example files. See the earlier comment on BasicPercent/styles.css about centralizing this shared pattern.

packages/third-party/motion/src/polyfill/element.ts (1)

57-66: Same type error at line 65.

This line has the same this.element.element type error as line 25. Refer to the verification requested in the earlier comment for the getComputedStyle method.

🧹 Nitpick comments (5)
examples/motion/src/ColorInterception/styles.css (1)

1-6: Consider extracting shared styles to reduce duplication.

The .case-container class is duplicated across multiple motion example stylesheets (Basic, BasicPercent, ColorInterception, Text, Stagger, Spring). Consider extracting this common class to a shared stylesheet (e.g., examples/motion/src/common.css) that can be imported by each example component.

packages/third-party/motion/package.json (1)

27-30: Update framer-motion to latest patch version.

framer-motion has a newer stable version available (12.23.24), whereas the current pinned version is 12.23.12. Consider updating to the latest patch. motion-dom@12.23.12 is already at the latest stable version.

examples/motion/src/BasicPercent/styles.css (1)

1-6: Consider centralizing the .case-container pattern.

The .case-container class with identical properties appears in multiple example stylesheets (BasicPercent, Text, and likely others). This duplication makes maintenance harder.

Consider moving this shared pattern to a common stylesheet (e.g., examples/motion/src/common.css) and importing it in the components that need it, or including it in the main App.css.

packages/third-party/motion/src/polyfill/element.ts (2)

33-41: Remove commented debug code.

The commented console.info statements at lines 34 and 40 should be removed to keep the codebase clean.

Apply this diff:

    styleObject.setProperty = (property: string, value: string) => {
-     // console.info('setStyleFrom style.setProperty')
      this.element.setStyleProperty(property, value);
    };
    return new Proxy(styleObject, {
      set: (target, prop, value) => {
        if (typeof prop === 'string' && prop !== 'setProperty') {
-         // console.info('setStyleFrom style.setter', prop)
          this.element.setStyleProperty(prop, String(value));

68-159: Consider using a proxy or helper to reduce duplication.

The 14 individual property getters/setters follow an identical pattern. While the current implementation is clear and functional, you could reduce duplication by using a proxy-based approach or a helper factory function.

This is a low-priority suggestion—the current explicit approach is acceptable and may provide better IDE autocomplete and type safety.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6acb37b and 39e92d5.

⛔ Files ignored due to path filters (4)
  • examples/motion/src/assets/arrow.png is excluded by !**/*.png
  • examples/motion/src/assets/lynx-logo.png is excluded by !**/*.png
  • examples/motion/src/assets/react-logo.png is excluded by !**/*.png
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (33)
  • .changeset/tame-cougars-cry.md (1 hunks)
  • examples/motion/lynx.config.js (1 hunks)
  • examples/motion/package.json (1 hunks)
  • examples/motion/src/App.css (1 hunks)
  • examples/motion/src/App.tsx (1 hunks)
  • examples/motion/src/Basic/index.tsx (1 hunks)
  • examples/motion/src/Basic/styles.css (1 hunks)
  • examples/motion/src/BasicPercent/index.tsx (1 hunks)
  • examples/motion/src/BasicPercent/styles.css (1 hunks)
  • examples/motion/src/ColorInterception/index.tsx (1 hunks)
  • examples/motion/src/ColorInterception/styles.css (1 hunks)
  • examples/motion/src/Spring/index.tsx (1 hunks)
  • examples/motion/src/Spring/styles.css (1 hunks)
  • examples/motion/src/Stagger/index.tsx (1 hunks)
  • examples/motion/src/Stagger/styles.css (1 hunks)
  • examples/motion/src/Text/index.tsx (1 hunks)
  • examples/motion/src/Text/styles.css (1 hunks)
  • examples/motion/src/index.tsx (1 hunks)
  • examples/motion/src/rspeedy-env.d.ts (1 hunks)
  • examples/motion/tsconfig.json (1 hunks)
  • packages/third-party/motion/README.md (1 hunks)
  • packages/third-party/motion/package.json (1 hunks)
  • packages/third-party/motion/src/animation/index.ts (1 hunks)
  • packages/third-party/motion/src/env_types/papi.d.ts (1 hunks)
  • packages/third-party/motion/src/index.ts (1 hunks)
  • packages/third-party/motion/src/polyfill/element.ts (1 hunks)
  • packages/third-party/motion/src/polyfill/shim.ts (1 hunks)
  • packages/third-party/motion/src/types/index.ts (1 hunks)
  • packages/third-party/motion/src/utils/noop.ts (1 hunks)
  • packages/third-party/motion/src/utils/registeredFunction.ts (1 hunks)
  • packages/third-party/motion/tsconfig.build.json (1 hunks)
  • packages/third-party/motion/tsconfig.json (1 hunks)
  • packages/third-party/tsconfig.json (1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
.changeset/*.md

📄 CodeRabbit inference engine (AGENTS.md)

For contributions, generate and commit a Changeset describing your changes

Files:

  • .changeset/tame-cougars-cry.md
🧠 Learnings (24)
📓 Common learnings
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1330
File: .changeset/olive-animals-attend.md:1-3
Timestamp: 2025-07-22T09:23:07.797Z
Learning: In the lynx-family/lynx-stack repository, changesets are only required for meaningful changes to end-users such as bugfixes and features. Internal/development changes like chores, refactoring, or removing debug info do not need changeset entries.
Learnt from: gaoachao
Repo: lynx-family/lynx-stack PR: 1736
File: .changeset/spotty-experts-smoke.md:1-3
Timestamp: 2025-09-12T09:43:04.847Z
Learning: In the lynx-family/lynx-stack repository, empty changeset files (containing only `---\n\n---`) are used for internal changes that modify src/** files but don't require meaningful release notes, such as private package changes or testing-only modifications. This satisfies CI requirements without generating user-facing release notes.
Learnt from: gaoachao
Repo: lynx-family/lynx-stack PR: 1736
File: .changeset/spotty-experts-smoke.md:1-3
Timestamp: 2025-09-12T09:43:04.847Z
Learning: In the lynx-family/lynx-stack repository, private packages (marked with "private": true in package.json) like lynx-js/react-transform don't require meaningful changeset entries even when their public APIs change, since they are not published externally and only affect internal development.
📚 Learning: 2025-09-18T08:12:56.802Z
Learnt from: Sherry-hue
Repo: lynx-family/lynx-stack PR: 1770
File: packages/web-platform/web-mainthread-apis/src/utils/processStyleInfo.ts:316-318
Timestamp: 2025-09-18T08:12:56.802Z
Learning: In packages/web-platform/web-mainthread-apis/src/utils/processStyleInfo.ts, the current implementation uses cardStyleElement.textContent += for lazy component styles. While this could theoretically invalidate rule indices by reparsing the stylesheet, Sherry-hue indicated that UIDs don't repeat for the same element, making this approach acceptable for now. A future optimization to use separate style elements per entry was discussed but deferred to a separate PR to keep the current lazy bundle PR focused.

Applied to files:

  • examples/motion/src/Stagger/styles.css
  • examples/motion/src/Text/styles.css
  • packages/third-party/motion/src/polyfill/element.ts
  • packages/third-party/motion/src/env_types/papi.d.ts
📚 Learning: 2025-11-03T08:47:17.714Z
Learnt from: Sherry-hue
Repo: lynx-family/lynx-stack PR: 1911
File: packages/web-platform/web-tests/tests/react/basic-element-list-estimated-main-axis-size-px/index.jsx:14-24
Timestamp: 2025-11-03T08:47:17.714Z
Learning: In the autoScroll method for XList components in the lynx-family/lynx-stack repository, the `rate` parameter supports plain strings like `'100'` in addition to numbers and strings with unit suffixes (`${number}px`, `${number}rpx`, `${number}ppx`), even though the TypeScript type definition may appear more restrictive.

Applied to files:

  • examples/motion/src/BasicPercent/index.tsx
  • examples/motion/src/rspeedy-env.d.ts
📚 Learning: 2025-08-12T16:09:32.413Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1497
File: packages/react/transform/tests/__swc_snapshots__/src/swc_plugin_snapshot/mod.rs/basic_full_static.js:9-10
Timestamp: 2025-08-12T16:09:32.413Z
Learning: In the Lynx stack, functions prefixed with `__` that are called in transformed code may be injected globally by the Lynx Engine at runtime rather than exported from the React runtime package. For example, `__CreateFrame` is injected globally by the Lynx Engine, not exported from lynx-js/react.

Applied to files:

  • packages/third-party/motion/src/index.ts
  • packages/third-party/motion/src/utils/registeredFunction.ts
  • packages/third-party/motion/src/utils/noop.ts
  • packages/third-party/motion/src/polyfill/shim.ts
  • examples/motion/src/index.tsx
  • examples/motion/lynx.config.js
  • packages/third-party/motion/src/env_types/papi.d.ts
📚 Learning: 2025-08-13T11:46:43.737Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1523
File: vitest.config.ts:5-6
Timestamp: 2025-08-13T11:46:43.737Z
Learning: In the lynx-stack codebase, default imports are consistently used for Node.js built-in modules (e.g., `import os from 'node:os'`, `import fs from 'node:fs'`). The TypeScript configuration supports esModuleInterop and allowSyntheticDefaultImports, making default imports the preferred pattern over namespace imports for Node.js built-ins.

Applied to files:

  • packages/third-party/motion/src/index.ts
  • examples/motion/src/rspeedy-env.d.ts
  • examples/motion/package.json
  • packages/third-party/motion/src/utils/noop.ts
  • packages/third-party/motion/src/polyfill/shim.ts
  • examples/motion/src/index.tsx
  • examples/motion/lynx.config.js
  • packages/third-party/motion/package.json
  • examples/motion/tsconfig.json
📚 Learning: 2025-09-12T09:43:04.847Z
Learnt from: gaoachao
Repo: lynx-family/lynx-stack PR: 1736
File: .changeset/spotty-experts-smoke.md:1-3
Timestamp: 2025-09-12T09:43:04.847Z
Learning: In the lynx-family/lynx-stack repository, empty changeset files (containing only `---\n\n---`) are used for internal changes that modify src/** files but don't require meaningful release notes, such as private package changes or testing-only modifications. This satisfies CI requirements without generating user-facing release notes.

Applied to files:

  • .changeset/tame-cougars-cry.md
  • examples/motion/package.json
  • packages/third-party/motion/README.md
  • examples/motion/lynx.config.js
  • packages/third-party/motion/package.json
📚 Learning: 2025-07-22T09:26:16.722Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1330
File: .changeset/olive-animals-attend.md:1-3
Timestamp: 2025-07-22T09:26:16.722Z
Learning: In the lynx-family/lynx-stack repository, CI checks require changesets when files matching the pattern "src/**" are modified (as configured in .changeset/config.json). For internal changes that don't need meaningful changesets, an empty changeset file is used to satisfy the CI requirement while not generating any release notes.

Applied to files:

  • .changeset/tame-cougars-cry.md
  • examples/motion/lynx.config.js
📚 Learning: 2025-07-22T09:23:07.797Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1330
File: .changeset/olive-animals-attend.md:1-3
Timestamp: 2025-07-22T09:23:07.797Z
Learning: In the lynx-family/lynx-stack repository, changesets are only required for meaningful changes to end-users such as bugfixes and features. Internal/development changes like chores, refactoring, or removing debug info do not need changeset entries.

Applied to files:

  • .changeset/tame-cougars-cry.md
📚 Learning: 2025-09-29T06:43:40.182Z
Learnt from: CR
Repo: lynx-family/lynx-stack PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-09-29T06:43:40.182Z
Learning: Applies to .changeset/*.md : For contributions, generate and commit a Changeset describing your changes

Applied to files:

  • .changeset/tame-cougars-cry.md
📚 Learning: 2025-08-27T08:10:09.932Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1612
File: packages/rspeedy/create-rspeedy/template-react-vitest-rltl-ts/src/tsconfig.json:3-13
Timestamp: 2025-08-27T08:10:09.932Z
Learning: In the lynx-family/lynx-stack repository, Rspeedy templates use `lynx-js/rspeedy/client` types via `rspeedy-env.d.ts` instead of `vite/client` types. Rspeedy provides its own client-side environment type definitions and doesn't require direct Vite type references.

Applied to files:

  • examples/motion/src/rspeedy-env.d.ts
  • examples/motion/package.json
  • packages/third-party/motion/src/polyfill/shim.ts
  • examples/motion/lynx.config.js
  • packages/third-party/motion/package.json
  • examples/motion/tsconfig.json
📚 Learning: 2025-08-06T13:28:57.182Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1453
File: vitest.config.ts:49-61
Timestamp: 2025-08-06T13:28:57.182Z
Learning: In the lynx-family/lynx-stack repository, the file `packages/rspeedy/create-rspeedy/template-react-vitest-rltl-js/vitest.config.js` is a template file for scaffolding new Rspeedy projects, not a test configuration that should be included in the main vitest projects array.

Applied to files:

  • examples/motion/src/rspeedy-env.d.ts
  • examples/motion/package.json
  • examples/motion/src/index.tsx
  • examples/motion/lynx.config.js
  • examples/motion/tsconfig.json
📚 Learning: 2025-08-21T08:46:54.494Z
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 1370
File: packages/webpack/cache-events-webpack-plugin/src/LynxCacheEventsRuntimeModule.ts:23-27
Timestamp: 2025-08-21T08:46:54.494Z
Learning: In Lynx webpack runtime modules, the team prioritizes performance and simplicity over defensive runtime error handling. They prefer relying on compile-time type safety (TypeScript) rather than adding runtime checks like try-catch blocks or type validation, especially for performance-critical code like cache event setup/cleanup functions.

Applied to files:

  • examples/motion/src/rspeedy-env.d.ts
  • examples/motion/package.json
  • packages/third-party/motion/src/utils/noop.ts
  • packages/third-party/motion/src/polyfill/shim.ts
  • examples/motion/src/index.tsx
📚 Learning: 2025-08-27T12:42:01.095Z
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 1616
File: packages/webpack/cache-events-webpack-plugin/test/cases/not-cache-events/lazy-bundle/index.js:3-3
Timestamp: 2025-08-27T12:42:01.095Z
Learning: In webpack, properties like __webpack_require__.lynx_ce are injected during compilation/build time when webpack processes modules and generates bundles, not at runtime when dynamic imports execute. Tests for such properties don't need to wait for dynamic imports to complete.

Applied to files:

  • examples/motion/src/rspeedy-env.d.ts
  • examples/motion/package.json
  • packages/third-party/motion/src/polyfill/shim.ts
  • examples/motion/src/index.tsx
  • examples/motion/lynx.config.js
📚 Learning: 2025-09-12T09:43:04.847Z
Learnt from: gaoachao
Repo: lynx-family/lynx-stack PR: 1736
File: .changeset/spotty-experts-smoke.md:1-3
Timestamp: 2025-09-12T09:43:04.847Z
Learning: In the lynx-family/lynx-stack repository, private packages (marked with "private": true in package.json) like lynx-js/react-transform don't require meaningful changeset entries even when their public APIs change, since they are not published externally and only affect internal development.

Applied to files:

  • examples/motion/package.json
  • packages/third-party/motion/src/utils/noop.ts
  • packages/third-party/motion/src/polyfill/shim.ts
  • examples/motion/src/index.tsx
  • examples/motion/lynx.config.js
  • packages/third-party/motion/package.json
  • examples/motion/tsconfig.json
📚 Learning: 2025-08-19T11:25:36.127Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1558
File: .changeset/solid-squids-fall.md:2-2
Timestamp: 2025-08-19T11:25:36.127Z
Learning: In the lynx-family/lynx-stack repository, changesets should use the exact package name from package.json#name, not generic or unscoped names. Each package has its own specific scoped name (e.g., "lynx-js/react-transform" for packages/react/transform).

Applied to files:

  • examples/motion/package.json
  • examples/motion/lynx.config.js
  • packages/third-party/motion/package.json
  • examples/motion/tsconfig.json
📚 Learning: 2025-08-06T13:28:57.182Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1453
File: vitest.config.ts:49-61
Timestamp: 2025-08-06T13:28:57.182Z
Learning: In the lynx-family/lynx-stack repository, the file `packages/react/testing-library/src/vitest.config.js` is source code for the testing library that gets exported for users, not a test configuration that should be included in the main vitest projects array.

Applied to files:

  • examples/motion/package.json
  • examples/motion/src/index.tsx
  • examples/motion/lynx.config.js
  • packages/third-party/motion/package.json
  • examples/motion/tsconfig.json
📚 Learning: 2025-08-11T05:59:28.530Z
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 1305
File: packages/react/testing-library/src/plugins/vitest.ts:4-6
Timestamp: 2025-08-11T05:59:28.530Z
Learning: In the lynx-family/lynx-stack repository, the `packages/react/testing-library` package does not have `vite` as a direct dependency. It relies on `vitest` being available from the monorepo root and accesses Vite types through re-exports from `vitest/node`. Direct imports from `vite` should not be suggested for this package.

Applied to files:

  • examples/motion/package.json
  • packages/third-party/motion/package.json
  • examples/motion/tsconfig.json
📚 Learning: 2025-11-06T01:19:23.670Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1917
File: packages/mcp-servers/devtool-mcp-server/tsconfig.json:8-8
Timestamp: 2025-11-06T01:19:23.670Z
Learning: The lynx-js/devtool-mcp-server package in lynx-family/lynx-stack targets Node.js >=18.19 (specified in its package.json engines), which is different from the root project's requirement of Node.js ^22 || ^24. The package uses "lib": ["ES2024.Promise"] in its tsconfig.json because it manually includes polyfills for Promise.withResolvers while maintaining compatibility with Node.js v18.

Applied to files:

  • examples/motion/package.json
  • packages/third-party/motion/package.json
  • examples/motion/tsconfig.json
📚 Learning: 2025-08-14T12:54:51.143Z
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 1370
File: .changeset/brave-melons-add.md:1-7
Timestamp: 2025-08-14T12:54:51.143Z
Learning: In the lynx-family/lynx-stack repository, packages use 0.x.x versioning where minor version bumps indicate breaking changes (not major bumps), following pre-1.0 semantic versioning conventions.

Applied to files:

  • packages/third-party/motion/README.md
  • packages/third-party/motion/package.json
📚 Learning: 2025-10-10T08:22:12.051Z
Learnt from: Sherry-hue
Repo: lynx-family/lynx-stack PR: 1837
File: packages/web-platform/web-mainthread-apis/src/prepareMainThreadAPIs.ts:266-266
Timestamp: 2025-10-10T08:22:12.051Z
Learning: In packages/web-platform/web-mainthread-apis, the handleUpdatedData function returned from prepareMainThreadAPIs is internal-only, used to serve web-core. It does not require public documentation, type exports, or SSR support.

Applied to files:

  • packages/third-party/motion/src/polyfill/shim.ts
📚 Learning: 2025-08-11T05:57:18.212Z
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 1305
File: packages/testing-library/testing-environment/src/index.ts:255-258
Timestamp: 2025-08-11T05:57:18.212Z
Learning: In the ReactLynx testing environment (`packages/testing-library/testing-environment/src/index.ts`), the dual assignment pattern `target.console.method = console.method = () => {}` is required for rstest compatibility. This is because rstest provides `console` in an IIFE (Immediately Invoked Function Expression), and both the target and global console need to have these methods defined for proper test execution.

Applied to files:

  • packages/third-party/motion/src/polyfill/shim.ts
📚 Learning: 2025-09-18T04:43:54.426Z
Learnt from: gaoachao
Repo: lynx-family/lynx-stack PR: 1771
File: packages/react/transform/tests/__swc_snapshots__/src/swc_plugin_snapshot/mod.rs/basic_component_with_static_sibling.js:2-2
Timestamp: 2025-09-18T04:43:54.426Z
Learning: In the lynx-family/lynx-stack repository, the `add_pure_comment` function in packages/react/transform/src/swc_plugin_compat/mod.rs (around lines 478-482) is specifically for `wrapWithLynxComponent` calls, not `createSnapshot` calls. The PURE comment injection for `createSnapshot` is handled separately in swc_plugin_snapshot/mod.rs.

Applied to files:

  • packages/third-party/motion/src/polyfill/shim.ts
📚 Learning: 2025-08-13T11:36:12.075Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1523
File: vitest.config.ts:52-72
Timestamp: 2025-08-13T11:36:12.075Z
Learning: The lynx-stack project requires Node.js >=22 as specified in package.json engines, so Node.js compatibility fallbacks for features introduced before v22 are unnecessary.

Applied to files:

  • packages/third-party/motion/package.json
📚 Learning: 2025-08-18T08:46:20.001Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1547
File: packages/rspeedy/core/src/config/loadConfig.ts:11-11
Timestamp: 2025-08-18T08:46:20.001Z
Learning: `#register` and similar imports starting with "#" are Node.js subpath imports defined in the "imports" field of package.json, not TypeScript path mapping aliases. These are natively supported by both Node.js and TypeScript without requiring additional tsconfig.json configuration like "moduleResolution" or "resolvePackageJsonImports" settings.

Applied to files:

  • examples/motion/tsconfig.json
  • packages/third-party/tsconfig.json
🧬 Code graph analysis (11)
examples/motion/src/Stagger/index.tsx (2)
packages/third-party/motion/src/animation/index.ts (2)
  • animate (58-58)
  • stagger (58-58)
packages/third-party/motion/src/index.ts (2)
  • animate (4-4)
  • stagger (4-4)
examples/motion/src/App.tsx (6)
examples/motion/src/BasicPercent/index.tsx (1)
  • Basic (7-57)
examples/motion/src/ColorInterception/index.tsx (1)
  • Basic (7-58)
examples/motion/src/Spring/index.tsx (1)
  • Basic (7-52)
examples/motion/src/Text/index.tsx (1)
  • Basic (7-47)
examples/motion/src/Basic/index.tsx (1)
  • BasicPercent (7-60)
examples/motion/src/Stagger/index.tsx (1)
  • Stagger (5-44)
examples/motion/src/ColorInterception/index.tsx (3)
examples/motion/src/BasicPercent/index.tsx (1)
  • Basic (7-57)
examples/motion/src/Spring/index.tsx (1)
  • Basic (7-52)
examples/motion/src/Text/index.tsx (1)
  • Basic (7-47)
examples/motion/src/BasicPercent/index.tsx (3)
examples/motion/src/ColorInterception/index.tsx (1)
  • Basic (7-58)
examples/motion/src/Spring/index.tsx (1)
  • Basic (7-52)
examples/motion/src/Text/index.tsx (1)
  • Basic (7-47)
packages/third-party/motion/src/utils/registeredFunction.ts (1)
packages/third-party/motion/src/utils/noop.ts (1)
  • noop (5-5)
examples/motion/src/Text/index.tsx (3)
examples/motion/src/BasicPercent/index.tsx (1)
  • Basic (7-57)
examples/motion/src/ColorInterception/index.tsx (1)
  • Basic (7-58)
examples/motion/src/Spring/index.tsx (1)
  • Basic (7-52)
packages/third-party/motion/src/polyfill/shim.ts (3)
packages/third-party/motion/src/polyfill/element.ts (1)
  • ElementCompt (11-159)
packages/react/runtime/__test__/utils/globals.js (1)
  • performance (16-44)
packages/web-platform/web-core/src/apis/LynxView.ts (1)
  • queueMicrotask (406-508)
examples/motion/src/index.tsx (1)
examples/motion/src/App.tsx (1)
  • App (39-66)
examples/motion/src/Spring/index.tsx (3)
examples/motion/src/BasicPercent/index.tsx (1)
  • Basic (7-57)
examples/motion/src/ColorInterception/index.tsx (1)
  • Basic (7-58)
examples/motion/src/Text/index.tsx (1)
  • Basic (7-47)
examples/motion/lynx.config.js (1)
packages/rspeedy/plugin-qrcode/src/index.ts (1)
  • pluginQRCode (91-155)
packages/third-party/motion/src/animation/index.ts (2)
packages/third-party/motion/src/utils/registeredFunction.ts (1)
  • registerCallable (8-12)
packages/third-party/motion/src/types/index.ts (1)
  • ElementOrElements (7-7)
🪛 GitHub Check: build / Build (Ubuntu)
packages/third-party/motion/src/polyfill/element.ts

[failure] 65-65:
Property 'element' does not exist on type 'Element'.


[failure] 25-25:
Property 'element' does not exist on type 'Element'.

🪛 GitHub Check: code-style-check
packages/third-party/motion/src/polyfill/element.ts

[failure] 65-65:
Property 'element' does not exist on type 'Element'.


[failure] 25-25:
Property 'element' does not exist on type 'Element'.

🪛 LanguageTool
.changeset/tame-cougars-cry.md

[grammar] ~1-~1: Hier könnte ein Fehler sein.
Context: --- ---

(QB_NEW_DE)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: build / Build (Windows)
  • GitHub Check: test-rust / Test (Ubuntu)
🔇 Additional comments (27)
examples/motion/src/rspeedy-env.d.ts (1)

1-1: LGTM! Follows the established Rspeedy pattern.

This type reference correctly includes the Rspeedy client type definitions, which is the standard pattern for Rspeedy projects in this repository.

Based on learnings

.changeset/tame-cougars-cry.md (1)

1-3: Empty changeset is appropriate for this private package.

This empty changeset satisfies CI requirements without generating user-facing release notes, which is the correct approach for the private @lynx-js/motion-lynx package.

Based on learnings.

packages/third-party/motion/README.md (1)

1-3: LGTM!

The README clearly indicates this is a work-in-progress port of motion.dev for Lynx, which is appropriate for this initial implementation.

packages/third-party/motion/src/utils/noop.ts (1)

1-5: LGTM!

Standard no-op utility implementation, correctly typed and ready for use as a default/fallback callback.

packages/third-party/motion/package.json (1)

19-20: Verify source-based entry points are intentional.

The main and types fields point to src/index.ts rather than built output in dist/. While acceptable for private development packages, ensure this aligns with your build and consumption strategy.

examples/motion/tsconfig.json (1)

1-19: LGTM!

The TypeScript configuration is properly set up for the motion examples with appropriate compiler options, file inclusions, and project references to dependency packages.

packages/third-party/motion/src/utils/registeredFunction.ts (2)

6-12: LGTM!

The registration logic correctly stores callable functions by ID and returns the ID for later retrieval.


19-25: Track the global pollution removal.

The global assignment to globalThis.runOnRegistered is noted as a temporary workaround (line 24 TODO). Ensure there's a plan or tracking issue to remove this global pollution once ReactLynx supports module imports for MTS.

Based on learnings.

packages/third-party/motion/src/index.ts (1)

1-4: LGTM!

Clean entry point with proper license header and straightforward re-exports.

examples/motion/src/App.css (1)

1-30: LGTM!

The CSS provides clear layout and styling for the motion example app UI.

examples/motion/src/index.tsx (1)

1-13: Standard entry point setup looks good.

The devtools imports, root rendering, and HMR configuration follow established patterns in the codebase.

packages/third-party/motion/tsconfig.json (1)

1-11: LGTM!

Standard TypeScript configuration following monorepo project reference patterns.

packages/third-party/motion/src/types/index.ts (1)

1-7: LGTM!

Clean type definition with proper license header. The ElementOrElements union type clearly expresses the API's ability to accept single or multiple elements.

examples/motion/src/App.tsx (1)

39-66: Well-structured component with clear responsibilities.

The App component provides a clean interface for switching between motion examples. The layout separates controls, status text, and the active example nicely.

examples/motion/src/Stagger/styles.css (1)

1-26: LGTM!

The CSS layout is well-structured for the stagger animation example, using flexbox appropriately to center and space the animated boxes.

examples/motion/src/Stagger/index.tsx (1)

12-12: Verify global lynx object availability on main thread.

The code uses lynx.querySelectorAll without importing or declaring it. Ensure this global object is available in the main-thread context where this function executes.

examples/motion/lynx.config.js (1)

1-20: LGTM!

The configuration is well-structured, appropriately enabling bundle analysis via environment variable and customizing the QR code for fullscreen mode in LynxExplorer.

examples/motion/src/ColorInterception/index.tsx (1)

40-40: Invoke the cleanup function immediately.

The cleanup should invoke runOnMainThread(endAnimation) immediately rather than scheduling it, or the animation may not stop properly on unmount.

Consider this adjustment:

  return () => {
-   runOnMainThread(endAnimation);
+   void runOnMainThread(endAnimation)();
  };

Likely an incorrect or invalid review comment.

packages/third-party/motion/src/animation/index.ts (4)

1-18: LGTM!

The imports are well-organized and the side-effect polyfill import is appropriate for setting up the runtime environment.


20-29: LGTM!

The conditional registration pattern correctly handles main-thread vs off-thread execution by registering the original framer-motion functions on the main thread and using string handles elsewhere.


31-47: LGTM!

The function correctly normalizes single elements and arrays into ElementCompt instances and delegates to the registered animate function. The 'main thread' directive ensures proper execution context.


49-58: LGTM!

The stagger function is a clean wrapper that delegates to the registered framer-motion stagger function with proper typing.

packages/third-party/motion/src/polyfill/shim.ts (3)

1-12: LGTM!

The imports and global type declarations are properly structured to extend the runtime environment.


49-52: Add runtime safety check for lynx global.

The code directly accesses lynx.querySelector and lynx.querySelectorAll without verifying the lynx global exists, which could cause a runtime error if the polyfill loads before the Lynx runtime is initialized.

Apply this diff to add a safety check:

  // @ts-expect-error error
  // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
- document.querySelector = lynx.querySelector;
+ document.querySelector = lynx?.querySelector;
  // @ts-expect-error error
  // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
- document.querySelectorAll = lynx.querySelectorAll;
+ document.querySelectorAll = lynx?.querySelectorAll;
⛔ Skipped due to learnings
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 1305
File: packages/testing-library/testing-environment/src/index.ts:255-258
Timestamp: 2025-08-11T05:57:18.212Z
Learning: In the ReactLynx testing environment (`packages/testing-library/testing-environment/src/index.ts`), the dual assignment pattern `target.console.method = console.method = () => {}` is required for rstest compatibility. This is because rstest provides `console` in an IIFE (Immediately Invoked Function Expression), and both the target and global console need to have these methods defined for proper test execution.
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 1370
File: packages/webpack/cache-events-webpack-plugin/src/LynxCacheEventsRuntimeModule.ts:23-27
Timestamp: 2025-08-21T08:46:54.494Z
Learning: In Lynx webpack runtime modules, the team prioritizes performance and simplicity over defensive runtime error handling. They prefer relying on compile-time type safety (TypeScript) rather than adding runtime checks like try-catch blocks or type validation, especially for performance-critical code like cache event setup/cleanup functions.
Learnt from: PupilTong
Repo: lynx-family/lynx-stack PR: 1292
File: packages/web-platform/web-core-server/src/createLynxView.ts:144-151
Timestamp: 2025-07-15T10:00:56.154Z
Learning: In the lynx-stack codebase, PupilTong prefers the "let it crash" approach over defensive null safety checks when the condition should never occur in normal operation. This applies to cases like the `element.getAttribute(lynxUniqueIdAttribute)!` call in SSR event capture where the attribute is expected to always be present.
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 1616
File: packages/webpack/cache-events-webpack-plugin/test/cases/not-cache-events/lazy-bundle/index.js:3-3
Timestamp: 2025-08-27T12:42:01.095Z
Learning: In webpack, properties like __webpack_require__.lynx_ce are injected during compilation/build time when webpack processes modules and generates bundles, not at runtime when dynamic imports execute. Tests for such properties don't need to wait for dynamic imports to complete.
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1497
File: packages/react/transform/tests/__swc_snapshots__/src/swc_plugin_snapshot/mod.rs/basic_full_static.js:9-10
Timestamp: 2025-08-12T16:09:32.413Z
Learning: In the Lynx stack, functions prefixed with `__` that are called in transformed code may be injected globally by the Lynx Engine at runtime rather than exported from the React runtime package. For example, `__CreateFrame` is injected globally by the Lynx Engine, not exported from lynx-js/react.
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1917
File: packages/mcp-servers/devtool-mcp-server/src/tools/DOM/QuerySelector.ts:13-16
Timestamp: 2025-11-06T01:17:10.259Z
Learning: In the Lynx implementation of the Chrome DevTools Protocol, the `nodeId` parameter can be omitted in `DOM.querySelector` and will default to the root node, which differs from the standard CDP specification that requires either `nodeId`, `backendNodeId`, or `objectId`.
Learnt from: gaoachao
Repo: lynx-family/lynx-stack PR: 1771
File: packages/react/transform/tests/__swc_snapshots__/src/swc_plugin_snapshot/mod.rs/basic_component_with_static_sibling.js:2-2
Timestamp: 2025-09-18T04:43:54.426Z
Learning: In the lynx-family/lynx-stack repository, the `add_pure_comment` function in packages/react/transform/src/swc_plugin_compat/mod.rs (around lines 478-482) is specifically for `wrapWithLynxComponent` calls, not `createSnapshot` calls. The PURE comment injection for `createSnapshot` is handled separately in swc_plugin_snapshot/mod.rs.
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 1670
File: packages/webpack/css-extract-webpack-plugin/test/hotCases/hot/hot-update-json/dual-thread/__snapshot__/index.css:6-8
Timestamp: 2025-09-23T08:54:39.966Z
Learning: In the lynx-stack CSS extract webpack plugin tests, many test fixture CSS files intentionally use invalid CSS syntax like `color: 'red';` with quoted values. The snapshots correctly reflect this invalid CSS from the source fixtures. To fix CSS validation issues, the source fixture files should be updated first, then snapshots regenerated, rather than manually editing snapshots.
Learnt from: Sherry-hue
Repo: lynx-family/lynx-stack PR: 1911
File: packages/web-platform/web-elements/src/XList/ListItemAttributes.ts:24-29
Timestamp: 2025-11-03T08:44:10.706Z
Learning: In packages/web-platform/web-elements/src/XList/ListItemAttributes.ts, the `estimated-main-axis-size-px` attribute handler does not need to validate or guard against invalid/NaN values when parsing - data correctness verification is not required for this attribute.
Learnt from: gaoachao
Repo: lynx-family/lynx-stack PR: 1771
File: packages/react/transform/tests/__swc_snapshots__/src/swc_plugin_snapshot/mod.rs/basic_component_with_static_sibling.js:2-2
Timestamp: 2025-09-18T04:43:54.426Z
Learning: In packages/react/transform/src/swc_plugin_compat/mod.rs, the `add_pure_comment` function at lines 478-482 is specifically for `wrapWithLynxComponent` calls, not `createSnapshot` calls. The PURE comment injection for `createSnapshot` is handled separately in swc_plugin_snapshot/mod.rs. These are two distinct code paths that should be treated differently.
Learnt from: PupilTong
Repo: lynx-family/lynx-stack PR: 1029
File: packages/web-platform/web-core/src/uiThread/createRenderAllOnUI.ts:95-99
Timestamp: 2025-07-16T06:28:26.463Z
Learning: In the lynx-stack codebase, CSS selectors in SSR hydration are generated by their own packages, ensuring a predictable format that makes simple string manipulation safe and preferable over regex for performance reasons.
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1523
File: vitest.config.ts:5-6
Timestamp: 2025-08-13T11:46:43.737Z
Learning: In the lynx-stack codebase, default imports are consistently used for Node.js built-in modules (e.g., `import os from 'node:os'`, `import fs from 'node:fs'`). The TypeScript configuration supports esModuleInterop and allowSyntheticDefaultImports, making default imports the preferred pattern over namespace imports for Node.js built-ins.

28-40: Empty stub classes are sufficient for this polyfill context.

The shim creates empty placeholders for globalThis, but all elements passed to framer-motion are wrapped with ElementCompt instances, which provide complete implementations of necessary methods (getComputedStyle(), style property, and style getters/setters like backgroundColor, color, fontSize, width, etc.). The window.getComputedStyle stub correctly delegates to ElementCompt.getComputedStyle(). Since ElementCompt handles all required DOM-like access patterns, instanceof checks on the wrapper instances succeed within the polyfill's design, and the empty stubs serve their intended purpose as globalThis placeholders. The code is functional as evidenced by its production-ready state.

packages/third-party/motion/src/polyfill/element.ts (2)

1-9: LGTM!

The StyleObject interface is well-defined to support both direct property access and the setProperty method.


18-28: Clarify intent of type suppression for this.element.element property access.

The identified type error is real and intentional: lines 25 and 65 access this.element.element, which is not in the documented MainThread.Element API. However, both usages include explicit @ts-expected-error Expected comments, indicating this is a deliberate workaround.

Before flagging as an error, confirm whether:

  • MainThread.Element has an undocumented .element property containing the native ElementNode expected by __GetComputedStyleByKey
  • This suppression pattern is the appropriate solution or should be refactored
  • The code path is tested and working as intended

If the suppression is appropriate, document why this internal property access is necessary. If not, refactor to use the public API.

Comment thread examples/motion/src/App.tsx Outdated
Comment thread examples/motion/src/Basic/index.tsx Outdated
Comment thread examples/motion/src/Basic/index.tsx Outdated
Comment thread examples/motion/src/Basic/index.tsx Outdated
Comment thread examples/motion/src/BasicPercent/index.tsx Outdated
Comment thread examples/motion/src/Text/index.tsx Outdated
Comment thread packages/motion/package.json
Comment thread packages/third-party/motion/src/polyfill/element.ts Outdated
Comment thread packages/third-party/motion/src/polyfill/shim.ts Outdated
Comment thread packages/third-party/motion/src/utils/registeredFunction.ts Outdated
@f0rdream f0rdream force-pushed the motion_lynx branch 3 times, most recently from b09e21e to aa393b3 Compare November 13, 2025 11:22
@codspeed-hq
Copy link
Copy Markdown

codspeed-hq Bot commented Nov 13, 2025

CodSpeed Performance Report

Merging this PR will degrade performance by 6.8%

Comparing f0rdream:motion_lynx (5a6a2b2) with main (1a5f2a1)

Summary

❌ 1 regressed benchmark
✅ 62 untouched benchmarks
⏩ 3 skipped benchmarks1

⚠️ Please fix the performance issues or acknowledge them on CodSpeed.

Performance Changes

Benchmark BASE HEAD Efficiency
basic-performance-nest-level-100 6.9 ms 7.5 ms -6.8%

Footnotes

  1. 3 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

@relativeci
Copy link
Copy Markdown

relativeci Bot commented Nov 13, 2025

Web Explorer

#7409 Bundle Size — 383.56KiB (0%).

5a6a2b2(current) vs 1a5f2a1 main#7408(baseline)

Bundle metrics  Change 1 change
                 Current
#7409
     Baseline
#7408
No change  Initial JS 154.71KiB 154.71KiB
No change  Initial CSS 35.05KiB 35.05KiB
No change  Cache Invalidation 0% 0%
No change  Chunks 8 8
No change  Assets 8 8
Change  Modules 238(-0.42%) 239
No change  Duplicate Modules 16 16
No change  Duplicate Code 2.99% 2.99%
No change  Packages 4 4
No change  Duplicate Packages 0 0
Bundle size by type  no changes
                 Current
#7409
     Baseline
#7408
No change  JS 252.66KiB 252.66KiB
No change  Other 95.85KiB 95.85KiB
No change  CSS 35.05KiB 35.05KiB

Bundle analysis reportBranch f0rdream:motion_lynxProject dashboard


Generated by RelativeCIDocumentationReport issue

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 10

♻️ Duplicate comments (5)
examples/motion/src/BasicPercent/index.tsx (1)

36-41: Cleanup function does not invoke the main thread scheduler.

The cleanup on line 39 calls runOnMainThread(endAnimation) without invoking the returned function, so endAnimation never executes and the animation continues running after unmount (resource leak). Line 37 correctly invokes runOnMainThread(startAnimation)() with (), but line 39 is missing the invocation.

Apply this diff to fix the cleanup:

   useEffect(() => {
     void runOnMainThread(startAnimation)();
     return () => {
-      void runOnMainThread(endAnimation);
+      void runOnMainThread(endAnimation)();
     };
   }, []);
examples/motion/src/Spring/index.tsx (1)

31-36: Critical: Cleanup function does not invoke the animation stop.

On line 34, runOnMainThread(endAnimation) returns a function but does not invoke it. Without the () invocation, endAnimation never executes when the component unmounts, leaving the animation running and potentially causing memory leaks.

Apply this diff:

   useEffect(() => {
     void runOnMainThread(startAnimation)();
     return () => {
-      void runOnMainThread(endAnimation);
+      void runOnMainThread(endAnimation)();
     };
   }, []);
examples/motion/src/Text/index.tsx (2)

20-22: Fix type mismatch: convert numeric latest to string for setAttribute.

The onUpdate callback receives a numeric value from the animation (0 to 100), but setAttribute is typed to accept (name: string, value: string). Explicitly convert the number to string to match the API contract:

 onUpdate: (latest) => {
-  textMTRef.current?.setAttribute('text', latest);
+  textMTRef.current?.setAttribute('text', String(latest));
 },

36-36: Invoke cleanup function to stop animation on unmount.

The cleanup is missing () to invoke the function returned by runOnMainThread. Currently, void runOnMainThread(endAnimation); calls runOnMainThread but never executes the returned function, so the animation never stops. This causes a resource leak and continued animation after unmount.

 return () => {
-  void runOnMainThread(endAnimation);
+  void runOnMainThread(endAnimation)();
 };

This matches the pattern used on line 34 for starting the animation.

packages/third-party/motion/src/polyfill/shim.ts (1)

9-21: Consider preferring a native high‑resolution timer when available

The performance.now shim is now monotonic and relative (👍), but it still uses Date.now() (millisecond, wall‑clock). Motion/framer‑motion’s frameloop is designed around a high‑resolution, monotonic clock. If Lynx exposes a more precise monotonic timer (or a proxy to native performance.now()/time origin), consider:

  • Using the native high‑res source when present, and
  • Falling back to this Date.now() - timeOrigin implementation only when nothing better is available.

This keeps current behavior but future‑proofs animation timing if a better clock exists in the host environment.

🧹 Nitpick comments (3)
packages/third-party/motion/src/polyfill/element.ts (1)

18-28: Consider declaring __GetComputedStyleByKey in a global .d.ts instead of repeated @ts-expect-error

Both getComputedStyle and getStyleProperty rely on the global __GetComputedStyleByKey and suppress TypeScript with @ts-expect-error. To make this safer and easier to maintain, you could declare its type once in a shared ambient declaration, e.g.:

// e.g. packages/third-party/motion/src/types/globals.d.ts
declare function __GetComputedStyleByKey(
  element: unknown,
  property: string,
): string;

Then you can remove the @ts-expect-error and ESLint suppression here while still reflecting the engine‑injected global behavior.

Also applies to: 59-63

packages/third-party/motion/__tests__/animation.test.tsx (1)

46-51: Remove leftover console.log from the test component

console.log('renderApp'); will spam test output and isn’t needed for the behavior being asserted. It’s better to drop it once debugging is done:

-      console.log('renderApp');
-
      function startAnimation() {
packages/third-party/motion/src/animation/index.ts (1)

31-52: Use mixHandle consistently instead of hardcoded 'mix'

All other wrappers (animate, stagger, motionValue, spring, springValue) call runOnRegistered with their handle variables, but mix uses the hardcoded 'mix' string even though mixHandle is set above. This is inconsistent and could break if registerCallable ever changes how it maps IDs.

Recommend switching mix to use mixHandle:

 function mix<T>(from: T, to: T): Mixer<T> {
   'main thread';
   // @TODO: Remove the globalThis trick when MTS can treat a module as MTS module
-  return globalThis.runOnRegistered<typeof mixOrig>('mix')(from, to);
+  return globalThis.runOnRegistered<typeof mixOrig>(mixHandle)(from, to);
 }

Also applies to: 143-147

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 39e92d5 and daf0ccd.

⛔ Files ignored due to path filters (4)
  • examples/motion/src/assets/arrow.png is excluded by !**/*.png
  • examples/motion/src/assets/lynx-logo.png is excluded by !**/*.png
  • examples/motion/src/assets/react-logo.png is excluded by !**/*.png
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (39)
  • .changeset/tame-cougars-cry.md (1 hunks)
  • examples/motion/lynx.config.js (1 hunks)
  • examples/motion/package.json (1 hunks)
  • examples/motion/src/App.css (1 hunks)
  • examples/motion/src/App.tsx (1 hunks)
  • examples/motion/src/Basic/index.tsx (1 hunks)
  • examples/motion/src/Basic/styles.css (1 hunks)
  • examples/motion/src/BasicPercent/index.tsx (1 hunks)
  • examples/motion/src/BasicPercent/styles.css (1 hunks)
  • examples/motion/src/BasicSelector/index.tsx (1 hunks)
  • examples/motion/src/BasicSelector/styles.css (1 hunks)
  • examples/motion/src/ColorInterception/index.tsx (1 hunks)
  • examples/motion/src/ColorInterception/styles.css (1 hunks)
  • examples/motion/src/MotionValue/index.tsx (1 hunks)
  • examples/motion/src/MotionValue/styles.css (1 hunks)
  • examples/motion/src/Spring/index.tsx (1 hunks)
  • examples/motion/src/Spring/styles.css (1 hunks)
  • examples/motion/src/Stagger/index.tsx (1 hunks)
  • examples/motion/src/Stagger/styles.css (1 hunks)
  • examples/motion/src/Text/index.tsx (1 hunks)
  • examples/motion/src/Text/styles.css (1 hunks)
  • examples/motion/src/index.tsx (1 hunks)
  • examples/motion/src/rspeedy-env.d.ts (1 hunks)
  • examples/motion/tsconfig.json (1 hunks)
  • packages/third-party/motion/README.md (1 hunks)
  • packages/third-party/motion/__tests__/animation.test.tsx (1 hunks)
  • packages/third-party/motion/package.json (1 hunks)
  • packages/third-party/motion/src/animation/index.ts (1 hunks)
  • packages/third-party/motion/src/env_types/papi.d.ts (1 hunks)
  • packages/third-party/motion/src/index.ts (1 hunks)
  • packages/third-party/motion/src/polyfill/element.ts (1 hunks)
  • packages/third-party/motion/src/polyfill/shim.ts (1 hunks)
  • packages/third-party/motion/src/types/index.ts (1 hunks)
  • packages/third-party/motion/src/utils/noop.ts (1 hunks)
  • packages/third-party/motion/src/utils/registeredFunction.ts (1 hunks)
  • packages/third-party/motion/tsconfig.build.json (1 hunks)
  • packages/third-party/motion/tsconfig.json (1 hunks)
  • packages/third-party/motion/vitest.config.ts (1 hunks)
  • packages/third-party/tsconfig.json (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • examples/motion/src/App.css
🚧 Files skipped from review as they are similar to previous changes (22)
  • examples/motion/package.json
  • examples/motion/src/ColorInterception/styles.css
  • packages/third-party/motion/README.md
  • examples/motion/src/Stagger/styles.css
  • examples/motion/tsconfig.json
  • examples/motion/src/Basic/index.tsx
  • packages/third-party/tsconfig.json
  • examples/motion/lynx.config.js
  • examples/motion/src/Spring/styles.css
  • examples/motion/src/App.tsx
  • packages/third-party/motion/tsconfig.build.json
  • packages/third-party/motion/src/index.ts
  • packages/third-party/motion/package.json
  • packages/third-party/motion/src/utils/registeredFunction.ts
  • examples/motion/src/rspeedy-env.d.ts
  • examples/motion/src/Basic/styles.css
  • .changeset/tame-cougars-cry.md
  • packages/third-party/motion/tsconfig.json
  • examples/motion/src/Text/styles.css
  • packages/third-party/motion/src/env_types/papi.d.ts
  • examples/motion/src/index.tsx
  • examples/motion/src/BasicPercent/styles.css
🧰 Additional context used
🧠 Learnings (17)
📓 Common learnings
Learnt from: gaoachao
Repo: lynx-family/lynx-stack PR: 1736
File: .changeset/spotty-experts-smoke.md:1-3
Timestamp: 2025-09-12T09:43:04.847Z
Learning: In the lynx-family/lynx-stack repository, private packages (marked with "private": true in package.json) like lynx-js/react-transform don't require meaningful changeset entries even when their public APIs change, since they are not published externally and only affect internal development.
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 1370
File: packages/webpack/cache-events-webpack-plugin/src/LynxCacheEventsRuntimeModule.ts:23-27
Timestamp: 2025-08-21T08:46:54.494Z
Learning: In Lynx webpack runtime modules, the team prioritizes performance and simplicity over defensive runtime error handling. They prefer relying on compile-time type safety (TypeScript) rather than adding runtime checks like try-catch blocks or type validation, especially for performance-critical code like cache event setup/cleanup functions.
📚 Learning: 2025-08-06T13:28:57.182Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1453
File: vitest.config.ts:49-61
Timestamp: 2025-08-06T13:28:57.182Z
Learning: In the lynx-family/lynx-stack repository, the file `packages/react/testing-library/src/vitest.config.js` is source code for the testing library that gets exported for users, not a test configuration that should be included in the main vitest projects array.

Applied to files:

  • packages/third-party/motion/vitest.config.ts
📚 Learning: 2025-08-06T13:28:57.182Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1453
File: vitest.config.ts:49-61
Timestamp: 2025-08-06T13:28:57.182Z
Learning: In the lynx-family/lynx-stack repository, the file `packages/rspeedy/create-rspeedy/template-react-vitest-rltl-js/vitest.config.js` is a template file for scaffolding new Rspeedy projects, not a test configuration that should be included in the main vitest projects array.

Applied to files:

  • packages/third-party/motion/vitest.config.ts
📚 Learning: 2025-08-11T05:59:28.530Z
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 1305
File: packages/react/testing-library/src/plugins/vitest.ts:4-6
Timestamp: 2025-08-11T05:59:28.530Z
Learning: In the lynx-family/lynx-stack repository, the `packages/react/testing-library` package does not have `vite` as a direct dependency. It relies on `vitest` being available from the monorepo root and accesses Vite types through re-exports from `vitest/node`. Direct imports from `vite` should not be suggested for this package.

Applied to files:

  • packages/third-party/motion/vitest.config.ts
📚 Learning: 2025-10-10T08:22:12.051Z
Learnt from: Sherry-hue
Repo: lynx-family/lynx-stack PR: 1837
File: packages/web-platform/web-mainthread-apis/src/prepareMainThreadAPIs.ts:266-266
Timestamp: 2025-10-10T08:22:12.051Z
Learning: In packages/web-platform/web-mainthread-apis, the handleUpdatedData function returned from prepareMainThreadAPIs is internal-only, used to serve web-core. It does not require public documentation, type exports, or SSR support.

Applied to files:

  • packages/third-party/motion/src/polyfill/shim.ts
📚 Learning: 2025-09-18T08:12:56.802Z
Learnt from: Sherry-hue
Repo: lynx-family/lynx-stack PR: 1770
File: packages/web-platform/web-mainthread-apis/src/utils/processStyleInfo.ts:316-318
Timestamp: 2025-09-18T08:12:56.802Z
Learning: In packages/web-platform/web-mainthread-apis/src/utils/processStyleInfo.ts, the current implementation uses cardStyleElement.textContent += for lazy component styles. While this could theoretically invalidate rule indices by reparsing the stylesheet, Sherry-hue indicated that UIDs don't repeat for the same element, making this approach acceptable for now. A future optimization to use separate style elements per entry was discussed but deferred to a separate PR to keep the current lazy bundle PR focused.

Applied to files:

  • packages/third-party/motion/src/polyfill/shim.ts
  • packages/third-party/motion/src/polyfill/element.ts
📚 Learning: 2025-08-11T05:57:18.212Z
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 1305
File: packages/testing-library/testing-environment/src/index.ts:255-258
Timestamp: 2025-08-11T05:57:18.212Z
Learning: In the ReactLynx testing environment (`packages/testing-library/testing-environment/src/index.ts`), the dual assignment pattern `target.console.method = console.method = () => {}` is required for rstest compatibility. This is because rstest provides `console` in an IIFE (Immediately Invoked Function Expression), and both the target and global console need to have these methods defined for proper test execution.

Applied to files:

  • packages/third-party/motion/src/polyfill/shim.ts
  • packages/third-party/motion/src/polyfill/element.ts
📚 Learning: 2025-08-12T16:09:32.413Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1497
File: packages/react/transform/tests/__swc_snapshots__/src/swc_plugin_snapshot/mod.rs/basic_full_static.js:9-10
Timestamp: 2025-08-12T16:09:32.413Z
Learning: In the Lynx stack, functions prefixed with `__` that are called in transformed code may be injected globally by the Lynx Engine at runtime rather than exported from the React runtime package. For example, `__CreateFrame` is injected globally by the Lynx Engine, not exported from lynx-js/react.

Applied to files:

  • packages/third-party/motion/src/polyfill/shim.ts
  • packages/third-party/motion/src/utils/noop.ts
📚 Learning: 2025-08-27T12:42:01.095Z
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 1616
File: packages/webpack/cache-events-webpack-plugin/test/cases/not-cache-events/lazy-bundle/index.js:3-3
Timestamp: 2025-08-27T12:42:01.095Z
Learning: In webpack, properties like __webpack_require__.lynx_ce are injected during compilation/build time when webpack processes modules and generates bundles, not at runtime when dynamic imports execute. Tests for such properties don't need to wait for dynamic imports to complete.

Applied to files:

  • packages/third-party/motion/src/polyfill/shim.ts
📚 Learning: 2025-08-21T08:46:54.494Z
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 1370
File: packages/webpack/cache-events-webpack-plugin/src/LynxCacheEventsRuntimeModule.ts:23-27
Timestamp: 2025-08-21T08:46:54.494Z
Learning: In Lynx webpack runtime modules, the team prioritizes performance and simplicity over defensive runtime error handling. They prefer relying on compile-time type safety (TypeScript) rather than adding runtime checks like try-catch blocks or type validation, especially for performance-critical code like cache event setup/cleanup functions.

Applied to files:

  • packages/third-party/motion/src/polyfill/shim.ts
  • packages/third-party/motion/src/utils/noop.ts
📚 Learning: 2025-08-27T08:10:09.932Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1612
File: packages/rspeedy/create-rspeedy/template-react-vitest-rltl-ts/src/tsconfig.json:3-13
Timestamp: 2025-08-27T08:10:09.932Z
Learning: In the lynx-family/lynx-stack repository, Rspeedy templates use `lynx-js/rspeedy/client` types via `rspeedy-env.d.ts` instead of `vite/client` types. Rspeedy provides its own client-side environment type definitions and doesn't require direct Vite type references.

Applied to files:

  • packages/third-party/motion/src/polyfill/shim.ts
📚 Learning: 2025-09-18T04:43:54.426Z
Learnt from: gaoachao
Repo: lynx-family/lynx-stack PR: 1771
File: packages/react/transform/tests/__swc_snapshots__/src/swc_plugin_snapshot/mod.rs/basic_component_with_static_sibling.js:2-2
Timestamp: 2025-09-18T04:43:54.426Z
Learning: In the lynx-family/lynx-stack repository, the `add_pure_comment` function in packages/react/transform/src/swc_plugin_compat/mod.rs (around lines 478-482) is specifically for `wrapWithLynxComponent` calls, not `createSnapshot` calls. The PURE comment injection for `createSnapshot` is handled separately in swc_plugin_snapshot/mod.rs.

Applied to files:

  • packages/third-party/motion/src/polyfill/shim.ts
📚 Learning: 2025-08-13T11:46:43.737Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1523
File: vitest.config.ts:5-6
Timestamp: 2025-08-13T11:46:43.737Z
Learning: In the lynx-stack codebase, default imports are consistently used for Node.js built-in modules (e.g., `import os from 'node:os'`, `import fs from 'node:fs'`). The TypeScript configuration supports esModuleInterop and allowSyntheticDefaultImports, making default imports the preferred pattern over namespace imports for Node.js built-ins.

Applied to files:

  • packages/third-party/motion/src/polyfill/shim.ts
  • packages/third-party/motion/src/utils/noop.ts
📚 Learning: 2025-09-12T09:43:04.847Z
Learnt from: gaoachao
Repo: lynx-family/lynx-stack PR: 1736
File: .changeset/spotty-experts-smoke.md:1-3
Timestamp: 2025-09-12T09:43:04.847Z
Learning: In the lynx-family/lynx-stack repository, private packages (marked with "private": true in package.json) like lynx-js/react-transform don't require meaningful changeset entries even when their public APIs change, since they are not published externally and only affect internal development.

Applied to files:

  • packages/third-party/motion/src/polyfill/shim.ts
  • packages/third-party/motion/src/utils/noop.ts
📚 Learning: 2025-10-11T06:16:12.517Z
Learnt from: Sherry-hue
Repo: lynx-family/lynx-stack PR: 1820
File: packages/web-platform/web-tests/tests/react.spec.ts:834-856
Timestamp: 2025-10-11T06:16:12.517Z
Learning: In packages/web-platform/web-tests/tests/react.spec.ts, the tests `basic-bindmouse` and `basic-mts-bindtouchstart` are NOT duplicates despite having similar test structures. They test different event types: `basic-bindmouse` validates mouse events (mousedown, mouseup, mousemove) with mouse-specific properties (button, buttons, x, y, pageX, pageY, clientX, clientY), while `basic-mts-bindtouchstart` validates touch events (touchstart) with touch arrays (touches, targetTouches, changedTouches). The similar test structure is coincidental and follows testing conventions.

Applied to files:

  • packages/third-party/motion/__tests__/animation.test.tsx
📚 Learning: 2025-11-03T08:47:17.714Z
Learnt from: Sherry-hue
Repo: lynx-family/lynx-stack PR: 1911
File: packages/web-platform/web-tests/tests/react/basic-element-list-estimated-main-axis-size-px/index.jsx:14-24
Timestamp: 2025-11-03T08:47:17.714Z
Learning: In the autoScroll method for XList components in the lynx-family/lynx-stack repository, the `rate` parameter supports plain strings like `'100'` in addition to numbers and strings with unit suffixes (`${number}px`, `${number}rpx`, `${number}ppx`), even though the TypeScript type definition may appear more restrictive.

Applied to files:

  • examples/motion/src/Text/index.tsx
  • examples/motion/src/BasicPercent/index.tsx
📚 Learning: 2025-11-03T08:44:10.706Z
Learnt from: Sherry-hue
Repo: lynx-family/lynx-stack PR: 1911
File: packages/web-platform/web-elements/src/XList/ListItemAttributes.ts:24-29
Timestamp: 2025-11-03T08:44:10.706Z
Learning: In packages/web-platform/web-elements/src/XList/ListItemAttributes.ts, the `estimated-main-axis-size-px` attribute handler does not need to validate or guard against invalid/NaN values when parsing - data correctness verification is not required for this attribute.

Applied to files:

  • examples/motion/src/Text/index.tsx
🧬 Code graph analysis (6)
examples/motion/src/BasicSelector/index.tsx (1)
examples/motion/src/Basic/index.tsx (1)
  • Basic (7-60)
packages/third-party/motion/src/polyfill/shim.ts (1)
packages/third-party/motion/src/polyfill/element.ts (1)
  • ElementCompt (11-156)
examples/motion/src/MotionValue/index.tsx (2)
examples/motion/src/Basic/index.tsx (1)
  • Basic (7-60)
packages/third-party/motion/src/index.ts (3)
  • animate (5-5)
  • MotionValue (13-13)
  • motionValue (7-7)
packages/third-party/motion/__tests__/animation.test.tsx (2)
packages/third-party/motion/src/animation/index.ts (1)
  • animate (149-149)
packages/third-party/motion/src/index.ts (1)
  • animate (5-5)
packages/third-party/motion/src/animation/index.ts (2)
packages/third-party/motion/src/utils/registeredFunction.ts (1)
  • registerCallable (8-12)
packages/third-party/motion/src/types/index.ts (1)
  • ElementOrElements (7-7)
examples/motion/src/ColorInterception/index.tsx (2)
packages/third-party/motion/src/animation/index.ts (1)
  • animate (149-149)
packages/third-party/motion/src/index.ts (1)
  • animate (5-5)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: build / Build (Ubuntu)
  • GitHub Check: build / Build (Windows)
  • GitHub Check: test-rust / Test (Ubuntu)
🔇 Additional comments (11)
examples/motion/src/Stagger/index.tsx (4)

1-3: LGTM!

The imports are appropriate and all dependencies are used within the component.


5-8: LGTM!

The component setup and main-thread ref initialization are correct. Using useMainThreadRef with the appropriate type annotation ensures type safety for the animator instance.


10-25: LGTM!

The animation functions are well-structured:

  • Both correctly marked with 'main thread' directive
  • The staggered animation configuration with infinite reverse repeat is appropriate for the demo
  • Proper use of useMainThreadRef to store and access the animator instance

34-43: LGTM!

The JSX structure is clean and the class names correctly match the selectors used in the animation functions. The four boxes provide a clear demonstration of the stagger effect.

examples/motion/src/ColorInterception/index.tsx (1)

1-36: LGTM: Well-structured main-thread animation implementation.

The component demonstrates proper use of Lynx's main-thread animation APIs:

  • Correct import of animate from the motion package
  • Proper typing of main-thread refs
  • Defensive null checks before starting animations
  • Safe optional chaining for cleanup
  • Appropriate use of 'main thread'; directives

The animation configuration with infinite reverse repetition is a good demonstration of the motion capabilities.

Also applies to: 44-57

examples/motion/src/MotionValue/styles.css (1)

1-6: LGTM! Consistent styling pattern.

The centering layout follows the same pattern used across other motion examples.

examples/motion/src/BasicSelector/styles.css (1)

1-6: LGTM!

The CSS styling correctly centers content using flexbox, consistent with the pattern used across other motion examples.

examples/motion/src/Spring/index.tsx (1)

7-29: LGTM!

The animation setup and teardown logic is well-structured. The use of useMainThreadRef for both the animation handle and target element, along with the spring animation configuration, follows the correct pattern for Lynx motion.

examples/motion/src/BasicSelector/index.tsx (1)

11-23: LGTM! Valid selector-based animation approach.

This component correctly demonstrates using a CSS selector (.box) to target elements for animation, which is a valid alternative to the ref-based approach used in the Basic example. The selector is evaluated on the main thread where the animate() call executes, and the 1-second delay ensures the element exists in the DOM.

packages/third-party/motion/src/utils/noop.ts (1)

1-5: Minimal noop utility looks correct and idiomatic

This is a straightforward shared no-op callback and is safe to use as a default handler across the motion utilities.

packages/third-party/motion/vitest.config.ts (1)

1-12: No changes needed — code follows established codebase pattern

The top-level await with createVitestConfig() is the consistent pattern used throughout this repository. At least 9 files across multiple packages (packages/testing-library, packages/rspeedy, packages/react/testing-library, packages/use-sync-external-store, and packages/third-party/motion) follow this exact same approach. Since createVitestConfig() is an async function, the top-level await pattern is intentional and aligned with the codebase's established conventions. While Vitest technically supports async factory functions, refactoring this file to use defineConfig(async () => {}) would introduce inconsistency with the rest of the repository.

Likely an incorrect or invalid review comment.

Comment thread examples/motion/src/BasicSelector/index.tsx
Comment thread examples/motion/src/ColorInterception/index.tsx
Comment thread examples/motion/src/MotionValue/index.tsx
Comment thread examples/motion/src/MotionValue/index.tsx Outdated
Comment thread examples/motion/src/MotionValue/index.tsx Outdated
Comment thread examples/motion/src/MotionValue/index.tsx Outdated
Comment thread examples/motion/src/Stagger/index.tsx
Comment thread packages/third-party/motion/__tests__/animation.test.tsx Outdated
Comment thread packages/motion/src/polyfill/element.ts
Comment thread packages/third-party/motion/src/types/index.ts Outdated
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
packages/third-party/motion/src/hooks/useMotionValueRef.ts (1)

16-36: Clarify initialization semantics and worklet/main‑thread wiring in useMotionValueRef

A couple of points worth double‑checking here:

  • useMemo with an empty deps array is used purely for side effects and captures value once. If value is intended to be only the initial motion value, this is fine, but it would be good to document that contract; if callers might pass a changing value, they won’t see it reflected after the first render.
  • Because this is side‑effectful setup (runOnMainThread / runWorkletCtx), using useEffect instead of useMemo would better express intent and avoid any confusion around memoization semantics, unless you specifically need this to run during render rather than post‑commit.
  • The runWorkletCtx(setMotionValue as unknown as Worklet, [value as WorkletRef<unknown>]) path relies on T being compatible with WorkletRef<unknown>, but T is unconstrained. If in practice T is always a worklet ref (or a shape compatible with it), consider constraining T or making that assumption explicit to avoid accidental misuse.

If these behaviors are intentional and mirror existing Lynx patterns, a short comment on “initial only” semantics and the expected shape of T would help future readers.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between daf0ccd and 37f1592.

📒 Files selected for processing (9)
  • packages/third-party/motion/package.json (1 hunks)
  • packages/third-party/motion/src/animation/index.ts (1 hunks)
  • packages/third-party/motion/src/hooks/useMotionEvent.ts (1 hunks)
  • packages/third-party/motion/src/hooks/useMotionValueRef.ts (1 hunks)
  • packages/third-party/motion/src/index.ts (1 hunks)
  • packages/third-party/motion/src/modified/motionValue.ts (1 hunks)
  • packages/third-party/motion/src/utils/isMainThreadElement.ts (1 hunks)
  • packages/third-party/motion/tsconfig.build.json (1 hunks)
  • packages/third-party/motion/tsconfig.json (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (6)
  • packages/third-party/motion/tsconfig.build.json
  • packages/third-party/motion/tsconfig.json
  • packages/third-party/motion/src/index.ts
  • packages/third-party/motion/src/utils/isMainThreadElement.ts
  • packages/third-party/motion/package.json
  • packages/third-party/motion/src/animation/index.ts
🧰 Additional context used
🧬 Code graph analysis (2)
packages/third-party/motion/src/hooks/useMotionEvent.ts (2)
packages/third-party/motion/src/animation/index.ts (1)
  • useMotionValueRefEvent (243-243)
packages/third-party/motion/src/index.ts (2)
  • useMotionValueRefEvent (12-12)
  • MotionValue (17-17)
packages/third-party/motion/src/modified/motionValue.ts (2)
packages/third-party/motion/src/index.ts (2)
  • MotionValue (17-17)
  • motionValue (7-7)
packages/third-party/motion/src/animation/index.ts (1)
  • motionValue (242-242)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: build / Build (Windows)
  • GitHub Check: test-rust / Test (Ubuntu)
🔇 Additional comments (3)
packages/third-party/motion/src/modified/motionValue.ts (3)

14-19: LGTM!

The factory function implementation is clean and correctly instantiates CustomMotionValue while returning the base MotionValue<V> type. The generic typing and parameter forwarding are properly handled.


5-6: Imports are correctly sourced from motion-dom.

The motion-dom package exports both MotionValue and MotionValueOptions, confirming that the imports at lines 5-6 are valid and properly referenced.


8-12: The toJSON override is intentional and correct; no changes needed.

MotionValue objects contain internal state and references that form non-serializable objects, which can cause JSON.stringify to fail. The toJSON() override returning an empty object is a recognized safe pattern in motion libraries to handle serialization of MotionValue instances and prevents serialization errors on circular references.

This override is not a bug—it's a deliberate defensive measure. No code in the Lynx codebase attempts to serialize MotionValue instances, so this behavior has no negative impact. The design is correct as-is.

Likely an incorrect or invalid review comment.

Comment thread packages/third-party/motion/src/hooks/useMotionEvent.ts Outdated
Comment thread .changeset/tame-cougars-cry.md
Comment thread packages/motion/src/env_types/papi.d.ts
Comment thread packages/motion/src/hooks/useMotionValueRef.ts
Comment thread packages/motion/src/utils/isMainThreadElement.ts
@Yradex
Copy link
Copy Markdown
Collaborator

Yradex commented Jan 27, 2026

@codex review

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 8b891d4376

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread packages/motion/src/mini/core/animate.ts
Comment thread packages/motion/src/utils/elementHelper.ts
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Fix all issues with AI agents
In `@packages/motion/src/animation/index.ts`:
- Around line 132-147: The selector-resolution logic fails for selector strings
with array-format keyframes; update the condition so selector strings are
resolved to DOM elements when optionsOrKeyframes is either a keyframes object or
a keyframes array. Concretely, add a check (e.g., isKeyframesArray =
Array.isArray(optionsOrKeyframes)) and change the resolution guard around
elementOrSelector2Dom(subjectOrSequence...) (currently using !isStringSubject ||
isKeyframesObject) to include isKeyframesArray so it becomes (!isStringSubject
|| isKeyframesObject || isKeyframesArray) — keep references to
subjectOrSequence, optionsOrKeyframes, isStringSubject, isKeyframesObject,
elementOrSelector2Dom, and realSubjectOrSequence when making the change.

In `@packages/motion/src/mini/core/animate.ts`:
- Around line 68-79: The code incorrectly overrides an explicit options.velocity
=== 0 because startVelocity = startVelocity || value.getVelocity() treats 0 as
falsy; update the logic in animate.ts around the startVelocity resolution
(variables: startVelocity, options.velocity, value.getVelocity(), value) so that
when options.velocity is explicitly provided (including 0) it is used, otherwise
fall back to value.getVelocity(); implement this by checking for undefined/null
(e.g., use nullish coalescing or explicit !== undefined) rather than truthiness
to decide whether to call value.getVelocity().
- Around line 103-114: The stop() implementation in controls currently sets
canceled and calls detach but never settles completionPromise, leaving awaiters
hanging; modify controls.stop to also call resolvePromise (guarded with
resolvePromise?) to resolve the completionPromise when cancelling (and
optionally clear resolvePromise after calling it) so any awaiting callers of
animate(...) will settle; locate symbols controls.stop, resolvePromise,
completionPromise, detach, and canceled to implement this change.

Comment thread packages/motion/src/animation/index.ts
Comment thread packages/motion/src/mini/core/animate.ts
Comment thread packages/motion/src/mini/core/animate.ts
Comment thread packages/motion/src/mini/core/MotionValue.ts Outdated
Comment thread packages/motion/src/utils/registeredFunction.ts
Comment thread packages/motion/src/modified/motionValue.ts Outdated
Comment thread packages/motion/package.json Outdated
Comment thread packages/motion/src/mini/core/animate.ts Outdated
Comment thread packages/motion/README.md
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Fix all issues with AI agents
In `@packages/motion/src/mini/core/animate.ts`:
- Around line 23-90: The animate function accepts AnimationOptions.type that
includes 'decay' and 'keyframes' but the implementation only handles
spring/tween; add a guard at the start of animate to explicitly reject
unsupported types (e.g., throw or return an error) when options.type is 'decay'
or 'keyframes' (or otherwise handle them explicitly), so those values don't
silently fall into the spring/tween path; update the validation near the top of
animate (where currentV and startVelocity are resolved) to check options.type
and fail-fast with a clear error message referencing AnimationOptions.type and
animate.
- Around line 105-191: The controls.then() promise can hang if stop() or the
completion path runs before then() is called because resolvePromise is set only
when the Promise is created but then() may be called after resolution; add a
settled flag (e.g., let settled = false) that you set to true when stop() or the
completion block calls resolvePromise, update controls.then to check settled and
call the callback immediately (and return completionPromise) so then() won't
hang, and ensure stop(), the finished branch (where resolvePromise is called),
and any detach path all set settled = true when resolving.

Comment thread packages/motion/src/mini/core/animate.ts
Comment thread packages/motion/src/mini/core/animate.ts
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Fix all issues with AI agents
In `@packages/motion/package.json`:
- Around line 1-17: The package.json for the scoped package "@lynx-js/motion" is
missing the publishConfig.access setting required for public npm publishing; add
a "publishConfig" object with "access": "public" to package.json (e.g., ensure
publishConfig.access is set to "public" alongside the existing "private": false
and metadata) so the package will publish as public on npm.

In `@packages/motion/README.md`:
- Line 51: Update the sentence that currently reads "Motion Mini is a
lightweight, **main-thread-optimized** version of the library. It provides a
core subset of animation capabilities designed for high performance and low
bundle size." to hyphenate the compound adjectives — e.g., change "high
performance" to "high-performance" and "low bundle size" to "low-bundle-size"
(or alternatively rephrase to "high performance and a low bundle size") so the
phrase after "core subset of animation capabilities designed for..." is
grammatically clear; locate the sentence containing "main-thread-optimized" and
the phrase "high performance and low bundle size" to apply the fix.
🧹 Nitpick comments (1)
packages/motion/src/mini/core/animate.ts (1)

23-35: Consider narrowing type to supported values only.

The type union includes 'keyframes' | 'decay' which throws at runtime (lines 84-86). Narrowing to 'spring' | undefined would provide compile-time safety for consumers of this mini API.

🔧 Proposed fix
 export interface AnimationOptions {
-  type?: 'spring' | 'keyframes' | 'decay';
+  type?: 'spring';
   stiffness?: number;

Alternatively, if maintaining API parity with motion.dev is a goal, keeping the broader type is acceptable given the runtime guard.

Comment thread packages/motion/package.json
Comment thread packages/motion/README.md
@f0rdream f0rdream requested review from HuJean and Yradex January 28, 2026 13:00
@colinaaa colinaaa merged commit b020525 into lynx-family:main Jan 29, 2026
46 of 47 checks passed
colinaaa pushed a commit that referenced this pull request Feb 1, 2026
This PR was opened by the [Changesets
release](https://github.com/changesets/action) GitHub action. When
you're ready to do a release, you can merge this and the packages will
be published to npm automatically. If you're not ready to do a release
yet, that's fine, whenever you add more changesets to main, this PR will
be updated.


# Releases
## @lynx-js/motion@0.0.2

### Patch Changes

- Add initial support for `@lynx-js/motion`
([#1062](#1062))

## @lynx-js/react@0.116.2

### Patch Changes

- Fix "TypeError: not a function" error caused by `replaceAll` not
supported in ES5.
([#2142](#2142))

- Bump `swc_core` v56.
([#2154](#2154))

- Use `disableDeprecatedWarning` option to suppress BROKEN warnings
during compilation.
([#2157](#2157))

1. BROKEN: `getNodeRef`/`getNodeRefFromRoot`/`createSelectorQuery` on
component instance is broken and MUST be migrated in ReactLynx 3.0,
please use ref or lynx.createSelectorQuery instead.
2. BROKEN: `getElementById` on component instance is broken and MUST be
migrated in ReactLynx 3.0, please use ref or lynx.getElementById
instead.

- Fix memory leak by clearing list callbacks when \_\_DestroyLifetime
event is triggered.
([#2112](#2112))

## @lynx-js/rspeedy@0.13.3

### Patch Changes

-   Updated dependencies \[]:
    -   @lynx-js/web-rsbuild-server-middleware@0.19.7

## @lynx-js/qrcode-rsbuild-plugin@0.4.4

### Patch Changes

- Bump `@clack/prompts` v1.0
([#2171](#2171))

## @lynx-js/react-rsbuild-plugin@0.12.7

### Patch Changes

- Updated dependencies
\[[`92881e7`](92881e7),
[`1a5f2a1`](1a5f2a1)]:
    -   @lynx-js/template-webpack-plugin@0.10.3
    -   @lynx-js/css-extract-webpack-plugin@0.7.0
    -   @lynx-js/react-webpack-plugin@0.7.3
    -   @lynx-js/react-alias-rsbuild-plugin@0.12.7
    -   @lynx-js/use-sync-external-store@1.5.0
    -   @lynx-js/react-refresh-webpack-plugin@0.3.4

## @lynx-js/web-constants@0.19.7

### Patch Changes

-   Updated dependencies \[]:
    -   @lynx-js/web-worker-rpc@0.19.7

## @lynx-js/web-core@0.19.7

### Patch Changes

- feat: add browser config of lynx-view, now you can customize the
browser config of lynx-view:
([#2140](#2140))

        lynxView.browserConfig = {
          pixelRatio: 1,
          pixelWidth: 1234,
          pixelHeight: 5678,
        }

-   Updated dependencies \[]:
    -   @lynx-js/web-constants@0.19.7
    -   @lynx-js/web-mainthread-apis@0.19.7
    -   @lynx-js/web-worker-rpc@0.19.7
    -   @lynx-js/web-worker-runtime@0.19.7

## @lynx-js/web-core-wasm@0.0.2

### Patch Changes

- Updated dependencies
\[[`43fc7e7`](43fc7e7)]:
    -   @lynx-js/web-elements@0.11.1
    -   @lynx-js/web-worker-rpc@0.19.7

## @lynx-js/web-elements@0.11.1

### Patch Changes

- feat: add wheel event handling and corresponding tests for
x-foldview-ng
([#2145](#2145))

## @lynx-js/web-mainthread-apis@0.19.7

### Patch Changes

-   Updated dependencies \[]:
    -   @lynx-js/web-constants@0.19.7

## @lynx-js/web-worker-runtime@0.19.7

### Patch Changes

-   Updated dependencies \[]:
    -   @lynx-js/web-constants@0.19.7
    -   @lynx-js/web-mainthread-apis@0.19.7
    -   @lynx-js/web-worker-rpc@0.19.7

## @lynx-js/template-webpack-plugin@0.10.3

### Patch Changes

- Fix "Failed to load CSS update file" for lazy bundle
([#2150](#2150))

- Fix "TypeError: cannot read property 'call' of undefined" error of
lazy bundle HMR.
([#2146](#2146))

## create-rspeedy@0.13.3



## @lynx-js/react-alias-rsbuild-plugin@0.12.7



## upgrade-rspeedy@0.13.3



## @lynx-js/web-core-server@0.19.7



## @lynx-js/web-rsbuild-server-middleware@0.19.7



## @lynx-js/web-worker-rpc@0.19.7

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
@coderabbitai coderabbitai Bot mentioned this pull request Apr 23, 2026
3 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants