Refactor VisualElement to motion-dom package#3470
Conversation
This refactoring moves the core VisualElement classes from framer-motion to motion-dom, making them framework-agnostic: - VisualElement base class with injectable feature definitions - DOMVisualElement, HTMLVisualElement, SVGVisualElement - ObjectVisualElement for animating plain JS objects - Feature base class - visualElementStore - Animation state management utilities - Variant resolution utilities - Reduced motion utilities - Projection geometry, styles, and animation utilities React-specific code (features, contexts, hooks) remains in framer-motion. The projection node core is kept in framer-motion due to complex React deps. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
VisualElement to motion-dom package
Code Review SummaryThis PR successfully refactors the VisualElement architecture from framer-motion to motion-dom, making it framework-agnostic. The changes are well-structured and comprehensive. Strengths
Potential Issues
Code QualityNaming, structure, dependencies all follow conventions correctly. No security or performance concerns. RecommendationHigh-quality refactor. Issues noted are minor. Approve with minor suggestions. Review by Claude Code |
- Delete barrel files that were just re-exporting from motion-dom - Update all imports to use motion-dom directly - Add eachAxis to motion-dom exports - Delete duplicate files: mix-values.ts, each-axis.ts, has-transform.ts, measure.ts - Delete projection geometry barrel files: models.ts, delta-calc.ts, delta-apply.ts, delta-remove.ts, copy.ts, conversion.ts, utils.ts - Delete projection styles barrel files: types.ts, scale-border-radius.ts, scale-box-shadow.ts, scale-correction.ts, transform.ts, transform-origin.ts - Delete render utils barrel files: variant-props.ts, is-variant-label.ts - Update test files to import from motion-dom instead of deleted barrel files Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Pull Request Review - Refactor VisualElement to motion-dom packageOverviewThis is a well-structured architectural refactoring that successfully moves the core Code Quality ✅Strengths:
Minor observations:
Architecture ✅Excellent dependency flow: Key improvements:
Potential Issues 🟡1. Type Compatibility (Low risk)The moved types like Check: Run 2. Circular Dependency Risk (Low risk)The
Recommendation: Consider adding integration tests that verify feature mounting/unmounting works correctly with the new structure. 3. Animation State Injection (Low risk)The Performance Considerations ✅Positive impacts:
No concerns identified in terms of performance degradation. Security Concerns ✅No security issues identified. This is a refactoring PR with:
Test Coverage ✅Excellent test coverage:
Test migration quality:
RecommendationsCritical (None) ✅High Priority
Medium Priority
Low Priority
Specific Code NotesExcellent Patterns Found:// packages/motion-dom/src/render/VisualElement.ts:64-66
export function setFeatureDefinitions(definitions: Partial<FeatureDefinitions>) {
featureDefinitions = definitions
}This injection pattern is clean and avoids tight coupling. Areas to Watch:// packages/motion-dom/src/render/Feature.ts:13
node: any // Typed as any to avoid circular dependenciesWhile pragmatic, ensure this doesn't mask type errors in consuming code. SummaryThis is a high-quality refactoring that achieves its goals effectively: ✅ Approve with confidence - The code quality is excellent, test coverage is comprehensive, and the architecture is sound. ✅ Low risk - This is a structural refactoring with no behavior changes. The passing CI and 869 passing tests provide strong confidence. ✅ Future-proof - This change sets up the codebase well for future framework-agnostic uses of motion-dom. Final Score: 9/10 - Excellent work. The only minor deduction is for the Review generated with attention to the repository's CLAUDE.md conventions and architectural patterns. |
Code Review - PR #3470: Refactor
|
- Move animation interfaces (animateMotionValue, animateTarget, animateVariant, animateVisualElement) to motion-dom - Move animation utilities (getDefaultTransition, isTransitionDefined, getFinalKeyframe, calcChildStagger) to motion-dom - Move optimized-appear utilities to motion-dom - Move will-change utilities to motion-dom - Move setTarget to motion-dom - Consolidate Feature class in motion-dom with proper VisualElement typing - Update all framer-motion imports to use motion-dom exports - Delete duplicate files from framer-motion Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Code Review: Refactor
|
PR Review: Refactor
|
| Priority | Issue | Recommendation |
|---|---|---|
| Medium | Initialization race condition | Add race-condition-safe initialization pattern |
| Low | Type safety in makeAnimateFunction | Add explicit return type annotation |
| Low | Feature definition mutation | Create new object instead of mutating |
| Low | Export organization | Document public vs internal exports |
✅ Conclusion
This is a well-executed refactor that significantly improves the architecture of the codebase. The changes are logical, well-tested, and maintain backward compatibility. The issues identified are minor and can be addressed in follow-up PRs if desired.
Recommendation: ✅ APPROVE with minor suggestions
The core refactor is solid, and the identified issues are low-risk quality-of-life improvements rather than blockers.
Great work on this architectural improvement! 🎉
Code Review: Refactor
|
Import from motion-dom instead of having a local copy. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Pull Request Review: Refactor VisualElement to motion-domSummaryThis is a well-executed architectural refactoring that successfully moves the core ✅ StrengthsArchitecture & Design
Code Quality
Migration Quality
🔍 Observations & Minor Concerns1. Circular Dependency HandlingLocation: parent?: any // VisualElement<unknown> - circular reference handled at runtimeWhile the Files affected:
Recommendation: Document a future task to explore interface segregation to reduce 2. Type Assertion in Animation StateLocation: // @ts-expect-error - @mattgperry to figure if we should do something hereThis indicates unresolved type issues that should be addressed in a follow-up. Recommendation: Create a follow-up issue to resolve this type error properly rather than suppressing it. 3. Security - Attribute/Style SettingLocation: The SVG rendering uses
Current assessment: ✅ Appears safe as values flow through the motion value system and type checking, but worth monitoring. 4. Feature Definition InitializationLocation: The Recommendation: Verify this is called during 📊 Test Coverage Assessment
⚡ Performance Considerations
🔒 Security Assessment
📝 Code Style & ConventionsAll changes follow the repository's code style per
🎯 RecommendationsHigh PriorityNone - the refactor is production-ready as-is. Medium Priority
Low Priority
✨ ConclusionRecommendation: ✅ APPROVE This is a high-quality refactoring that achieves its architectural goals without compromising stability or introducing significant technical debt. The comprehensive test coverage (869 total tests passing) gives strong confidence in the changes. The few minor concerns noted are manageable and don't block merging. Great work on this refactor! The dependency injection pattern for feature definitions is particularly elegant and sets up the codebase well for future framework integrations beyond React. Review generated by Claude Code |
- Remove scrape-motion-values wrapper files from framer-motion - Update imports to use motion-dom exports directly - Import TransformOrigin and HTMLRenderState from motion-dom - Move scale-correction and svg scrape-motion-values tests to motion-dom Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Code Review: Refactor VisualElement to motion-dom packageSummaryThis PR successfully moves core VisualElement classes and related utilities from ✅ Strengths
🔍 Potential Issues & Recommendations1. Feature Definitions Initialization Timing (Medium Priority)Location: The let isInitialized = false
export function initFeatureDefinitions() {
if (isInitialized) return
// ...
setFeatureDefinitions(initialFeatureDefinitions)
isInitialized = true
}Concern: If a motion component is rendered before features are loaded via Recommendation: Consider adding a warning or explicit check to ensure 2. Deleted Test File Without Replacement (Low Priority)Location: The test file was deleted, but I don't see a corresponding test in Recommendation: Consider whether tests should be migrated to 3. Type Safety for Feature Definitions (Low Priority)Location: The feature definitions are stored in a module-level variable that can be mutated: let featureDefinitions: Partial<FeatureDefinitions> = {}
export function setFeatureDefinitions(definitions: Partial<FeatureDefinitions>) {
featureDefinitions = definitions
}Recommendation: Consider making this immutable after initialization or adding defensive checks to prevent accidental multiple calls that could override features unexpectedly. For example: export function setFeatureDefinitions(definitions: Partial<FeatureDefinitions>) {
if (Object.keys(featureDefinitions).length > 0) {
console.warn('Feature definitions already set')
}
featureDefinitions = definitions
}4. Import Organization (Code Style)Location: Multiple files, e.g., Some imports from import {
addValueToWillChange,
animateMotionValue,
calcLength,
convertBoundingBoxToBox,
// ... 15 more imports
} from "motion-dom"Recommendation: This is acceptable but consider whether some commonly used groups of utilities could be re-exported together from a subpath like 5. Missing Documentation for Breaking Changes (Low Priority)While the PR re-exports types to maintain compatibility, internal APIs have changed significantly. If any consumers import from deep paths (e.g., Recommendation: Consider adding a note in the PR description or changelog about avoiding deep imports. 🎯 Security & Performance
📝 Test Coverage AssessmentStrengths:
Gaps:
Recommendation: Consider adding a test file in ✅ Overall AssessmentThis is a well-executed refactor that improves the architecture of the codebase. The changes are logical, comprehensive, and maintain backwards compatibility. The concerns raised are mostly minor and don't block merging. Recommendation: ✅ Approve with minor suggestions The feature definition initialization pattern is the only item I'd recommend addressing before merge, and even that is optional if the team is confident about initialization order in practice. Great work on this significant refactor! 🎉 |
Move the entire projection node system from framer-motion to motion-dom to enable vanilla JS layout animations without React dependency. Files moved: - create-projection-node.ts, types.ts, state.ts, group.ts - HTMLProjectionNode.ts, DocumentProjectionNode.ts - stack.ts, flat-tree.ts, compare-by-depth.ts - delay.ts, add-dom-event.ts, resolve-motion-value.ts, single-value.ts - Projection node tests Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
PR Review: Refactor VisualElement to motion-domThis is a significant architectural refactoring that moves the core ✅ Strengths
|
| Category | Rating | Notes |
|---|---|---|
| Architecture | ⭐⭐⭐⭐ | Good separation of concerns, but initialization pattern needs work |
| Code Quality | ⭐⭐⭐⭐⭐ | Clean, well-structured code following conventions |
| Testing | ⭐⭐⭐⭐ | Comprehensive existing tests, but missing tests for new initialization pattern |
| Performance | ⭐⭐⭐⭐ | No obvious issues, but should monitor feature lookup overhead |
| Security | ⭐⭐⭐⭐⭐ | No concerns |
| Documentation | ⭐⭐⭐ | Needs documentation of new architecture |
Overall: ✅ Approve with recommendations
This is a solid refactoring that achieves its goal of making VisualElement framework-agnostic. The main concern is the feature definition initialization pattern, which should be hardened before merging. Consider addressing the high-priority issue around race conditions and adding explicit initialization calls.
🎯 Action Items
Before Merge (High Priority):
- Add explicit
initFeatureDefinitions()call in framer-motion entry point - Add runtime validation in
VisualElement.updateFeatures()for empty definitions - Add tests for feature definition initialization
- Update CLAUDE.md with new architecture documentation
After Merge (Medium Priority):
- Add integration tests for motion-dom standalone usage
- Profile performance of feature lookups in high-frequency scenarios
- Create migration guide if any internal APIs have changed
- Consider adding a framework adapter pattern for projection system
Future Considerations:
- Evaluate if the projection system needs further abstraction for non-React frameworks
- Consider exposing more granular exports from motion-dom for tree-shaking
- Document the plugin/feature architecture for third-party extensions
Great work on this significant refactoring! The code is well-structured and the approach is sound. With the initialization concerns addressed, this will be a solid foundation for framework-agnostic animations. 🚀
Summary
Test plan
yarn buildpasses for all packagesmake test- 703 unit tests passyarn test-playwright- 166 e2e tests pass🤖 Generated with Claude Code