Best fit
- 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.
affaan-m/ECC
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.
npx skills add https://github.com/affaan-m/ECC --skill "skills/motion-foundations"Source checked Jul 28, 2026·Refresh due Oct 26, 2026
Reorganized from the pinned upstream SKILL.md
According to the pinned SKILL.md from affaan-m/ECC: 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.
npx skills add https://github.com/affaan-m/ECC --skill "skills/motion-foundations"Best fit
Bring this context
Expected outputs
Key source sections
Sections are extracted automatically from the pinned SKILL.md and link back to the source.
Starting any animated component from scratch
A shared motionTokens object (duration, easing, distance, scale)
Motion must do at least one of the following or it must be removed:
These are non-negotiable. They apply to every component in the system.
Disable (make shouldAnimate() return false) when:
SkillSignal prompt templates
These prompts were written by SkillSignal from the source structure; they are not upstream text.
Task-start prompt
Confirm source fit, inputs, and outputs before acting.
Use motion-foundations to help me with: [specific task]. Context: [files, data, or background]. Constraints: [environment, scope, and prohibited actions]. Before acting, check the pinned SKILL.md and explain which sections apply, what inputs are still missing, and what you will deliver.
Source-guided execution
Make the Agent explicitly follow the key extracted sections.
Apply the pinned motion-foundations source to [task]. Pay particular attention to these source sections: “When to Activate”, “Outputs”, “Principles”, “Rules”, “Decision Guidance”. Preserve the important decision at each step. Mark facts not covered by the source as “needs confirmation” instead of inventing them. Then verify the result against my acceptance criteria: [criteria].
Result-review prompt
Check omissions, permissions, and source drift before delivery.
Review the current motion-foundations result: (1) does it satisfy the original task; (2) were any applicable steps or limits in the pinned SKILL.md missed; (3) did it perform any unauthorized file, command, network, or data action; and (4) which conclusions remain unverified? List issues first, then fix only what the source or user authorization supports.
Output checklist
The task matches the purpose documented in the SKILL.md.
The source section “When to Activate” has been checked.
The source section “Outputs” has been checked.
The source section “Principles” has been checked.
The source section “Rules” has been checked.
Inputs, constraints, and acceptance criteria are explicit.
Unverified facts, compatibility, and outcome claims are clearly marked.
Any file, command, network, or data action has been reviewed.
Choose a different workflow
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.
A separate implementation from affaan-m/ECC; compare its source, maintenance signals, and permission requirements.
Open source detailGuide 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
A separate implementation from vercel-labs/agent-skills; compare its source, maintenance signals, and permission requirements.
Open source detailFind the bugs a diff can actually ship: TypeScript, React, Next.js, OWASP, accessibility, SEO, database, and deploy-risk review. Return findings, not a grade.
A separate implementation from JasonColapietro/suede-creator-skills; compare its source, maintenance signals, and permission requirements.
Open source detailFAQ
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.
The catalog detected this source-specific install command: npx skills add https://github.com/affaan-m/ECC --skill "skills/motion-foundations". Inspect the command and pinned source before running it.
No dedicated Agent platform is declared in the pinned source record.
Quality breakdown
Based on traceable docs and repository signals; stars are not treated as quality.
Compare before choosing
These links are selected from shared tasks, functions, stacks, platforms, and same-name variants. Compare the source owner, documentation, permissions, and maintenance signals.
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.
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
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.
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
Accessibility patterns for React and Next.js — semantic HTML, ARIA attributes, form labeling, keyboard navigation, focus management, and screen reader support. Use when building any interactive UI component or form.
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-essential// 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 },
}
// 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
},
}
Priority 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.
// 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>
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 }}
/>
// 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>
)
}
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.