rc-motion
Lifecycle-driven CSSMotion primitives for React enter, leave, and list animations.
Repository Health
Technical Analysis
rc-motion (published as @rc-component/motion) is the motion engine behind Ant Design and the react-component ecosystem. It provides two declarative primitives, CSSMotion and CSSMotionList, that drive predictable appear, enter, and leave transitions by applying CSS class name phases across a component’s lifecycle.
Rather than animating values in JavaScript, rc-motion coordinates the timing of CSS transitions and animations, exposing prepare, start, active, and end hooks for each phase plus a deadline fallback for when transition events never fire. This makes it a dependable low-level building block for component libraries that need controllable, class-based motion.
What You Get
- A declarative CSSMotion component for appear, enter, and leave transitions
- CSSMotionList for animating keyed collections as items are added and removed
- Per-phase lifecycle callbacks (prepare, start, active, end) with inline-style patching
- A motionDeadline fallback that completes motion even when transition or animation events do not fire
- First-class TypeScript definitions and React ref forwarding to the DOM node
Common Use Cases
- Building accordion, dropdown, modal, and tooltip transitions inside a component library
- Animating list insertions and removals with correct keyed enter/leave choreography
- Adding class-based CSS transitions to elements that mount and unmount conditionally
- Providing predictable motion primitives for a design system such as Ant Design
Under The Hood
Architecture - The public surface in src/index.tsx exports the CSSMotion default component, the genCSSMotion factory, CSSMotionList, and a Provider from src/context.tsx used to globally disable motion. The core lifecycle lives in src/hooks/useStatus.ts, which tracks a status state machine (none | appear | enter | leave) and a step queue (prepare | start | active | end) defined in src/interface.ts; src/hooks/useStepQueue.ts and src/hooks/useNextFrame.ts sequence the steps across animation frames, while src/hooks/useDomMotionEvents.ts subscribes to transitionend/animationend and honours the motionDeadline timeout. CSSMotionList.tsx diffs successive keys via src/util/diff.ts to decide which children enter or leave.
Tech Stack - Written in TypeScript and shipped as both CommonJS (lib) and ES modules (es) built with father. Runtime dependencies are minimal: @rc-component/util for shared helpers and clsx for class composition, with react and react-dom (>=16.9) as peer dependencies. Documentation is authored with dumi and tests run under the rc-test (Jest) harness.
Code Quality - The repository has a substantial test suite (tests/CSSMotion.spec.tsx, tests/CSSMotionList.spec.tsx, tests/StrictMode.spec.tsx) using @testing-library/react plus snapshot fixtures, and enforces ESLint and strict TypeScript via tsc --noEmit. Logic is factored into small single-purpose hooks, and the state/step constants are modelled as discriminated unions for type safety.
API Design - The render-prop API is deliberately minimal: CSSMotion calls children({ className, style }, ref) so consumers stay in control of the rendered element, and the phase callbacks follow a consistent on<Phase><Stage> naming scheme. It powers Ant Design in production, and the README documents every prop, list prop, and ref method in dense tables, keeping the learning curve manageable for its low-level role.