with one click
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.
// 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.
Instinct-based learning system that observes sessions via hooks, creates atomic instincts with confidence scoring, and evolves them into skills/commands/agents. v2.1 adds project-scoped instincts to prevent cross-project contamination.
Use this skill when inspecting Blender characters, rigs, poses, animation retargeting, ground contact, facing direction, or model-vs-motion alignment where screenshots alone are not enough.
Suggests manual context compaction at logical intervals to preserve context through task phases rather than arbitrary auto-compaction.
Use when managing an Uncloud cluster — deploying services, configuring Caddy ingress, adding static proxy routes for non-cluster devices, publishing ports, scaling, inspecting logs, or managing machines and volumes with the `uc` CLI.
自動Claude Codeループのパターンとアーキテクチャ — シンプルな順序パイプラインからRFC駆動マルチエージェントDAGシステムまで。
Angular コードを生成し、アーキテクチャ ガイダンスを提供します。プロジェクトの作成、コンポーネント、またはサービスを作成するとき、または反応性(シグナル、linkedSignal、リソース)、フォーム、依存性注入、ルーティング、SSR、アクセシビリティ(ARIA)、アニメーション、スタイリング(コンポーネント スタイル、Tailwind CSS)、テスト、または CLI ツール作成のベスト プラクティスについてトリガーされます。
| name | motion-foundations |
| description | 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. |
| version | 1 |
| tags | ["motion","animation","performance","accessibility"] |
| category | frontend |
| author | jeff |
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.