Source profileQuality 79/100

affaan-m/ECC/skills/motion-foundations/SKILL.md

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.

Source repository stars
234,327
Declared platforms
0
Static risk flags
0
Last source update
2026-07-27
Source checked
2026-07-28

Decision brief

What it does—and where it fits

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.

Best for

    Not for

    • Tasks that require unconfirmed production actions or broad system permissions.
    • Environments where the pinned source and install steps cannot be inspected.

    Compatibility matrix

    Platform support, with evidence labels

    PlatformStatusEvidenceWhat to check
    CodexNot declaredNo explicit evidencePortability before use
    Claude CodeNot declaredNo explicit evidencePortability before use
    CursorNot declaredNo explicit evidencePortability before use
    Gemini CLINot declaredNo explicit evidencePortability before use
    Open the compatibility checker

    Installation

    Inspect first. Install second.

    The source command is displayed only when detected. A safe inspection prompt is always available so your agent can explain every action before execution.

    Source-detected install commandSource
    npx skills add https://github.com/affaan-m/ECC --skill "skills/motion-foundations"
    Safe inspection promptEditorial

    Inspect the Agent Skill "motion-foundations" from https://github.com/affaan-m/ECC/blob/4e973d3eaf92d97f8d2e2d8abb39d8bdc8711b38/skills/motion-foundations/SKILL.md at commit 4e973d3eaf92d97f8d2e2d8abb39d8bdc8711b38. List every install step, command, network request, credential, file read/write, external action, and rollback step. Explain whether it fits my task. Do not install or execute anything until I approve.

    Workflow

    What the source asks the agent to do

    1. 01

      When to Activate

      Starting any animated component from scratch

      Starting any animated component from scratchSetting up tokens, spring presets, or easing valuesImplementing prefers-reduced-motion support
    2. 02

      Outputs

      A shared motionTokens object (duration, easing, distance, scale)

      A shared motionTokens object (duration, easing, distance, scale)A shared springs preset map (5 named configs)A shouldAnimate() gate used by all components
    3. 03

      Principles

      Motion must do at least one of the following or it must be removed:

      Guide attentionCommunicate statePreserve spatial continuity
    4. 04

      Rules

      These are non-negotiable. They apply to every component in the system.

      Use 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.Reduced motion overrides everything. When useReducedMotion() returns true or prefersReduced is true, all transforms are disabled. Opacity-only fades at ≤ 0.2s are the only permitted fallback.
    5. 05

      Decision Guidance

      Disable (make shouldAnimate() return false) when:

      prefersReduced is trueisLowEnd is true and the animation is non-essentialThe element is off-screen and will never enter the viewport

    Permission review

    Static risk signals and limitations

    No configured static risk pattern was detected

    This is not proof of safety. Runtime behavior, indirect dependencies, and hidden external systems are outside the static scan.

    Evidence record

    Why each signal appears

    EvidenceSourceComputedTestedEditorial
    SignalValueEvidence typeMeaning
    Quality score79/100ComputedDocumentation, specificity, maintenance, and trust rules
    Repository stars234,327SourceRepository attention, not individual Skill quality
    Compatibility0 platformsSourceDeclared in the catalog source record
    Usage guideautomated source guideEditorialGenerated or reviewed according to the visible evidence level

    Pinned source

    Provenance and original SKILL.md

    Repository
    affaan-m/ECC
    Skill path
    skills/motion-foundations/SKILL.md
    Commit
    4e973d3eaf92d97f8d2e2d8abb39d8bdc8711b38
    License
    MIT
    Collected
    2026-07-28
    Default branch
    main
    View the original SKILL.md

    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.

    When to Activate

    • Starting any animated component from scratch
    • Setting up tokens, spring presets, or easing values
    • Implementing prefers-reduced-motion support
    • Debugging hydration mismatches from animation initial states
    • Evaluating whether an animation should exist at all

    Outputs

    This skill produces:

    • A shared motionTokens object (duration, easing, distance, scale)
    • A shared springs preset map (5 named configs)
    • A shouldAnimate() gate used by all components
    • Accessibility-compliant animation defaults via useReducedMotion
    • SSR-safe initial states with zero hydration warnings

    Principles

    Motion must do at least one of the following or it must be removed:

    • Guide attention
    • Communicate state
    • Preserve spatial continuity

    Responsiveness always outranks smoothness. A 60 fps animation that causes input delay is worse than no animation.

    Rules

    These are non-negotiable. They apply to every component in the system.

    1. Use motion/react only. Never import from framer-motion. Never mix the two in the same tree.
    2. initial must match server output. If the server renders opacity: 1, the initial prop must also be opacity: 1. No exceptions.
    3. Reduced motion overrides everything. When useReducedMotion() returns true or prefersReduced is true, all transforms are disabled. Opacity-only fades at ≤ 0.2s are the only permitted fallback.
    4. Never animate layout properties. width, height, top, left, margin, padding are banned from animate. Use transform and opacity only.
    5. All token values come from motionTokens. Hardcoded durations and easings in component files are forbidden.
    6. All spring configs come from the springs map. Inline stiffness/damping values are forbidden.
    7. "use client" is required on every file that imports from motion/react.
    8. Never read window or navigator at module level. Always guard with typeof window !== "undefined".

    Decision Guidance

    Choosing a duration

    TokenUse when
    instantTooltip show/hide, focus ring, badge update
    fastButton feedback, icon swap, chip toggle
    normalModal open, card expand, page element enter
    slowHero entrance, full-page transition
    crawlDeliberate storytelling; use sparingly

    Choosing a spring

    PresetUse when
    snappyDefault UI — buttons, chips, nav items
    gentleCards, modals, panels landing softly
    bouncyPlayful moments — empty states, onboarding
    instantTooltips, popovers, dropdowns
    releaseDrag release — natural physics feel

    When to disable animation entirely

    Disable (make shouldAnimate() return false) when:

    • prefersReduced is true
    • isLowEnd is true and the animation is non-essential
    • The element is off-screen and will never enter the viewport
    • The animation is purely decorative with no UX purpose

    Core Concepts

    Token system

    // lib/motion-tokens.ts
    export const motionTokens = {
      duration: {
        instant: 0.08,
        fast:    0.18,
        normal:  0.35,
        slow:    0.6,
        crawl:   1.0,
      },
      easing: {
        smooth: [0.22, 1, 0.36, 1],
        sharp:  [0.4, 0, 0.2, 1],
        bounce: [0.34, 1.56, 0.64, 1],
        linear: [0, 0, 1, 1],
      },
      distance: {
        xs: 4,
        sm: 8,
        md: 16,
        lg: 24,
        xl: 48,
      },
      scale: {
        subtle: 0.98,
        press:  0.95,
        pop:    1.04,
      },
    }
    
    export const springs = {
      snappy:  { type: "spring", stiffness: 300, damping: 30 },
      gentle:  { type: "spring", stiffness: 120, damping: 14 },
      bouncy:  { type: "spring", stiffness: 400, damping: 10 },
      instant: { type: "spring", stiffness: 600, damping: 35 },
      release: { type: "spring", stiffness: 200, damping: 20, restDelta: 0.001 },
    }
    

    Runtime flags

    // lib/motion-config.ts
    export const motionConfig = {
      isLowEnd() {
        return (
          typeof navigator !== "undefined" &&
          navigator.hardwareConcurrency <= 4
        )
      },
    
      prefersReduced() {
        return (
          typeof window !== "undefined" &&
          window.matchMedia("(prefers-reduced-motion: reduce)").matches
        )
      },
    
      shouldAnimate({ essential = false } = {}) {
        if (this.prefersReduced()) return false
        if (!essential && this.isLowEnd()) return false
        return true
      },
    
      duration() {
        return this.isLowEnd() || this.prefersReduced()
          ? motionTokens.duration.instant
          : motionTokens.duration.normal
      },
    }
    

    Accessibility

    Priority order (highest to lowest):

    1. prefers-reduced-motion: reduce — disables all transforms, limits opacity transitions to ≤ 0.2s
    2. Low-end device detection — reduces duration, removes non-essential animations
    3. Design preference — everything else

    Motion must degrade gracefully. It must never disappear abruptly in a way that causes layout shift or confuses orientation.

    // hooks/use-reduced-motion.tsx
    "use client"
    import { useReducedMotion } from "motion/react"
    
    export function useSafeMotion(fullY: number = 16) {
      const reduce = useReducedMotion()
      return {
        initial: { opacity: 0, y: reduce ? 0 : fullY },
        animate: { opacity: 1, y: 0 },
        exit:    { opacity: 0, y: reduce ? 0 : -fullY },
      }
    }
    
    /* globals.css */
    @media (prefers-reduced-motion: reduce) {
      .motion-safe-transition  { transition: opacity 0.15s; }
      .motion-reduce-transform { transform: none !important; }
    }
    
    <!-- Tailwind -->
    <div class="motion-safe:animate-fade motion-reduce:opacity-100"></div>
    

    SSR / hydration safety

    Rule: initial must always match what the server renders.

    // WRONG — server renders opacity:1 but initial says 0 → hydration mismatch
    <motion.div initial={{ opacity: 0 }} animate={{ opacity: 1 }} />
    
    // CORRECT — use AnimatePresence or defer to client mount
    "use client"
    const [mounted, setMounted] = useState(false)
    useEffect(() => setMounted(true), [])
    
    <motion.div
      initial={{ opacity: mounted ? 0 : 1 }}
      animate={{ opacity: 1 }}
    />
    

    Code Examples

    End-to-end: tokens + springs + accessibility + SSR guard

    // components/fade-in-card.tsx
    "use client"
    
    import { useState, useEffect } from "react"
    import { motion } from "motion/react"
    import { motionTokens, springs } from "@/lib/motion-tokens"
    import { useSafeMotion } from "@/hooks/use-reduced-motion"
    import { motionConfig } from "@/lib/motion-config"
    
    interface FadeInCardProps {
      children: React.ReactNode
      delay?: number
    }
    
    export function FadeInCard({ children, delay = 0 }: FadeInCardProps) {
      // SSR guard — initial must match server output (opacity: 1)
      const [mounted, setMounted] = useState(false)
      useEffect(() => setMounted(true), [])
    
      // Accessibility — disables transform when reduced motion is preferred
      const safeMotion = useSafeMotion(motionTokens.distance.md)
    
      // Device gate — skip animation on low-end hardware
      if (!motionConfig.shouldAnimate() || !mounted) {
        return <div>{children}</div>
      }
    
      return (
        <motion.div
          initial={safeMotion.initial}
          animate={safeMotion.animate}
          exit={safeMotion.exit}
          transition={{
            ...springs.gentle,
            delay,
          }}
          whileHover={{ scale: motionTokens.scale.pop }}
          whileTap={{ scale: motionTokens.scale.press }}
        >
          {children}
        </motion.div>
      )
    }
    

    Constraints / Non-Goals

    This skill does not cover:

    • UI component patterns (button, modal, stagger) → see motion-patterns
    • Drag, gestures, SVG, text animations, custom hooks → see motion-advanced
    • CSS-only animations or Tailwind animate-* classes without motion/react
    • Third-party animation libraries (GSAP, anime.js, etc.)
    • Motion design decisions (when to animate, what to emphasize) — that is a design concern, not a code constraint

    Anti-Patterns

    Anti-patternRule violatedFix
    import { motion } from "framer-motion"Rule 1Use motion/react
    initial={{ opacity: 0 }} on SSR componentRule 2Add mount guard
    Skipping useReducedMotion checkRule 3Use useSafeMotion hook
    animate={{ width: "100%" }}Rule 4Use scaleX transform instead
    transition={{ duration: 0.4 }} inlineRule 5Use motionTokens.duration.normal
    { stiffness: 300, damping: 30 } inlineRule 6Use springs.snappy
    Missing "use client" directiveRule 7Add to top of file
    navigator.hardwareConcurrency at module levelRule 8Wrap in typeof navigator !== "undefined"

    Related Skills

    • 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.

    Alternatives

    Compare before choosing

    Computed 90234,327

    affaan-m/ECC

    motion-patterns

    Production-ready animation patterns for React / Next.js — button, modal, toast, stagger, page transitions, exit animations, scroll, and layout — built on motion-foundations tokens and springs.

    Computed 8929,549

    vercel-labs/agent-skills

    vercel-react-view-transitions

    Guide for implementing smooth, native-feeling animations using React's View Transition API (`<ViewTransition>` component, `addTransitionType`, and CSS view transition pseudo-elements). Use this skill whenever the user wants to add page transitions, animate route changes, create shared element animations, animate enter/exit of components, animate list reorder, implement directional (forward/back) navigation animations, or integrate view transitions in Next.js. Also use when the user mentions view

    Computed 89165

    JasonColapietro/suede-creator-skills

    suede-code-review

    Find the bugs a diff can actually ship: TypeScript, React, Next.js, OWASP, accessibility, SEO, database, and deploy-risk review. Return findings, not a grade.

    Computed 8837,126

    github/awesome-copilot

    gsap-framer-scroll-animation

    Use this skill whenever the user wants to build scroll animations, scroll effects, parallax, scroll-triggered reveals, pinned sections, horizontal scroll, text animations, or any motion tied to scroll position — in vanilla JS, React, or Next.js. Covers GSAP ScrollTrigger (pinning, scrubbing, snapping, timelines, horizontal scroll, ScrollSmoother, matchMedia) and Framer Motion / Motion v12 (useScroll, useTransform, useSpring, whileInView, variants). Use this skill even if the user just says "anim