npx skills add ...
npx skills add affaan-m/ecc --skill motion-foundations
Motion tokens, spring presets, performance rules, device adaptation, accessibility enforcement, and SSR safety for React / Next.js using motion/react. Foundation layer — all other motion skills depend on this. Use when setting up motion tokens, spring presets, reduced-motion handling, or SSR-safe animation in React or Next.js.
npx skills add affaan-m/ecc --skill motion-foundations
The base layer of the motion system. Defines every value, constraint, and
rule that downstream skills (motion-patterns, motion-advanced) inherit.
Load this skill before any animation work begins.
prefers-reduced-motion supportThis skill produces:
motionTokens object (duration, easing, distance, scale)springs preset map (5 named configs)shouldAnimate() gate used by all componentsuseReducedMotionMotion must do at least one of the following or it must be removed:
Responsiveness always outranks smoothness. A 60 fps animation that causes input delay is worse than no animation.
These are non-negotiable. They apply to every component in the system.
motion/react only. Never import from framer-motion. Never mix the two in the same tree.initial must match server output. If the server renders opacity: 1, the initial prop must also be opacity: 1. No exceptions.useReducedMotion() returns true or prefersReduced is true, all transforms are disabled. Opacity-only fades at ≤ 0.2s are the only permitted fallback.width, height, top, left, margin, padding are banned from animate. Use transform and opacity only.motionTokens. Hardcoded durations and easings in component files are forbidden.springs map. Inline stiffness/damping values are forbidden."use client" is required on every file that imports from motion/react.window or navigator at module level. Always guard with typeof window !== "undefined".| Token | Use when |
|---|---|
instant | Tooltip show/hide, focus ring, badge update |
fast | Button feedback, icon swap, chip toggle |
normal | Modal open, card expand, page element enter |
slow | Hero entrance, full-page transition |
crawl | Deliberate storytelling; use sparingly |
| Preset | Use when |
|---|---|
snappy | Default UI — buttons, chips, nav items |
gentle | Cards, modals, panels landing softly |
bouncy | Playful moments — empty states, onboarding |
instant | Tooltips, popovers, dropdowns |
release | Drag release — natural physics feel |
Disable (make shouldAnimate() return false) when:
prefersReduced is trueisLowEnd is true and the animation is non-essentialPriority order (highest to lowest):
prefers-reduced-motion: reduce — disables all transforms, limits opacity transitions to ≤ 0.2sMotion must degrade gracefully. It must never disappear abruptly in a way that causes layout shift or confuses orientation.
Rule: initial must always match what the server renders.
This skill does not cover:
motion-patternsmotion-advancedanimate-* classes without motion/react| Anti-pattern | Rule violated | Fix |
|---|---|---|
import { motion } from "framer-motion" | Rule 1 | Use motion/react |
initial={{ opacity: 0 }} on SSR component | Rule 2 | Add mount guard |
Skipping useReducedMotion check | Rule 3 | Use useSafeMotion hook |
animate={{ width: "100%" }} | Rule 4 | Use scaleX transform instead |
transition={{ duration: 0.4 }} inline | Rule 5 | Use motionTokens.duration.normal |
{ stiffness: 300, damping: 30 } inline | Rule 6 | Use springs.snappy |
Missing "use client" directive | Rule 7 | Add to top of file |
navigator.hardwareConcurrency at module level | Rule 8 | Wrap in typeof navigator !== "undefined" |
motion-patterns — consumes tokens and springs defined here to build button, modal, stagger, page transition, and scroll patterns. Does not redefine any values.motion-advanced — consumes tokens and springs defined here for drag, SVG, text, and gesture patterns. Adds useAnimate sequences and custom hooks on top of this foundation.