Agent skill
motion-design-principles
Three-tier animation decision framework, composition rules, anti-patterns, and responsive animation principles. Foundation for all motion work.
Install this agent skill to your Project
npx add-skill https://github.com/adilkalam/orca/tree/main/skills/motion-design-principles
SKILL.md
Motion Design Principles
Three-Tier Animation Decision Tree
Choose the SIMPLEST tier that achieves the effect. Never escalate without reason.
Tier 1: CSS Scroll-Driven Animations
Use when: Simple reveals, hover effects, viewport-triggered fades.
Technology: CSS animation-timeline: scroll(), @keyframes, transition.
Advantages: Zero JS, best performance, compositor-only.
/* Tier 1 example: simple fade-up on scroll */
@keyframes fade-up {
from { opacity: 0; transform: translateY(var(--motion-reveal-distance, 40px)); }
to { opacity: 1; transform: translateY(0); }
}
.reveal-on-scroll {
animation: fade-up linear both;
animation-timeline: view();
animation-range: entry 0% entry 30%;
}
Decision: If a simple CSS scroll-driven animation achieves the effect, STOP HERE.
Tier 2: GSAP ScrollTrigger
Use when: Choreographed sequences, pinning, horizontal scroll, split text, staggered children, scrub-linked animations. Technology: GSAP 3 + ScrollTrigger plugin + optionally SplitText, Flip. Advantages: Timeline control, pin support, scrub, responsive via matchMedia.
Decision: If the effect needs timeline choreography, scrub, or pinning, use GSAP.
Tier 3: Three.js / WebGL
Use when: 3D scenes, particle systems, model rendering, camera scroll animation. Technology: three@0.169.0 (vanilla, NOT React Three Fiber). Advantages: Full 3D, GPU-powered, immersive experiences.
Decision: Only when the effect is inherently 3D. Never for 2D scroll effects.
Composition Rules
Stagger Timing
- Base stagger: use design-dna
motion.duration.stagger(default 0.12s) - Max visible staggers: 8-12 elements. Beyond that, use batch reveals.
- Stagger direction: follow reading order (left-to-right, top-to-bottom)
Easing Selection by Context
| Context | Easing | Design-DNA Token |
|---|---|---|
| Element entering viewport | Decelerate | motion.easing.entrance |
| Element leaving viewport | Accelerate | motion.easing.exit |
| Emphasis/attention | Elastic/bounce | motion.easing.emphasis |
| Continuous/scrub | Linear or none | motion.easing.smooth |
Duration Relationships
- Fast interactions (hover, click feedback):
motion.duration.fast(0.3s) - Standard reveals:
motion.duration.normal(0.6s) - Dramatic/hero sequences:
motion.duration.slow(1.0s) - Between-element stagger:
motion.duration.stagger(0.12s) - Rule: Longer distances = longer durations. Scale proportionally.
Do / Don't
DO
- Consume ALL timing/easing values from design-dna motion tokens
- Clean up ScrollTrigger instances on component unmount
- Use
gsap.matchMedia()for responsive animation differences - Use
will-changesparingly and remove after animation completes - Animate only
transformandopacitywhen possible (compositor-only) - Respect
prefers-reduced-motion: disable or simplify animations - Use
ScrollTrigger.batch()for many identical reveal animations
DON'T
- Hardcode animation values (durations, easings, distances)
- Mix
scrubandtoggleActionson the same ScrollTrigger - Put ScrollTrigger on child tweens inside a timeline (put it on the timeline)
- Animate layout properties (
width,height,top,left) -- use transforms - Use
transition: all-- list specific properties - Forget cleanup: always
tl.revert()orScrollTrigger.kill()on unmount - Create animations without testing on mobile viewports
Anti-Patterns
ScrollTrigger on Child Tweens (CRITICAL)
// WRONG: ScrollTrigger on individual tweens inside timeline
const tl = gsap.timeline();
tl.to('.a', { y: 0, scrollTrigger: { trigger: '.a' } }); // BUG
tl.to('.b', { y: 0, scrollTrigger: { trigger: '.b' } }); // BUG
// RIGHT: ScrollTrigger on the timeline itself
const tl = gsap.timeline({
scrollTrigger: { trigger: '.section', start: 'top center' }
});
tl.to('.a', { y: 0 });
tl.to('.b', { y: 0 });
Missing Cleanup
// WRONG: No cleanup
useEffect(() => {
gsap.to('.element', { scrollTrigger: { ... } });
}, []);
// RIGHT: Context-based cleanup
useEffect(() => {
const ctx = gsap.context(() => {
gsap.to('.element', { scrollTrigger: { ... } });
}, containerRef);
return () => ctx.revert();
}, []);
Missing Responsive Handling
// WRONG: Same animation at all viewport sizes
gsap.to('.hero', { x: 500 });
// RIGHT: Responsive via matchMedia
gsap.matchMedia().add('(min-width: 768px)', () => {
gsap.to('.hero', { x: 500 });
});
gsap.matchMedia().add('(max-width: 767px)', () => {
gsap.to('.hero', { x: 200 });
});
Responsive Animation Principles
- Always use
gsap.matchMedia()for viewport-dependent animations - Simplify on mobile: Reduce parallax intensity, disable horizontal scroll sections
- Touch considerations: No hover-dependent animations on mobile
- Performance budget: Fewer simultaneous animations on mobile
- Reduced motion: Check
prefers-reduced-motionand provide fallback
Performance Guidelines
- Batch similar animations:
ScrollTrigger.batch()for repeated reveals - Transforms only: Animate
transformandopacityfor 60fps - Will-change budget: Apply to max 3-5 elements simultaneously
- Lazy ScrollTrigger: Use
ScrollTrigger.create()with lazy refresh for off-screen content - Pin spacing: Always set
pinSpacing: true(default) unless layout requires otherwise
Recommended Agent Skills
Expand your agent's capabilities with these related and highly-rated skills.
web-interface-guidelines
Web UI quality rules: interactions, forms, loading, animations, layout, content, performance, accessibility, design. Apply to all web UI work. Adapted from Vercel Design Guidelines.
react-performance
React/Next.js performance patterns with wrong/right code examples. Apply when building or reviewing React components. Adapted from Vercel React Best Practices by @shuding.
stripe-integration
Payment integration patterns for Stripe. Covers checkout sessions, subscriptions, webhooks, idempotency, and the sharp edges that cause real-money bugs. Backend-agnostic with examples for Next.js App Router and Django REST Framework.
testing-strategy
Testing strategies and best practices for unit, integration, and end-to-end tests. Use when setting up test infrastructure, writing test cases, or deciding what to test. Covers test pyramid, mocking strategies, and coverage guidelines.
frontend-aesthetics
Global frontend aesthetics skill that helps Claude avoid generic "AI slop" UI and make bold, intentional visual decisions while still honoring each project's design-dna, tokens, and architecture.
pg-style-editor
Edit writing to adopt Paul Graham's exceptionally clear style for research and long-form content - concrete language, varied sentence rhythm, accessible formality, specific evidence. Use when user wants to rewrite content in PG's style or asks to "make this clearer" or "simplify research writing."
Didn't find tool you were looking for?