agentsclimarketplace

Design motion

Skill kensaurus/cursor-kenji/skills/design-motion

🦖Curated Cursor AI agent skills, slash commands, MCP configs, subagents & rules for full-stack dev — React 19, Next.js 15, Supabase, Tailwind v4, TypeScript

Install
npx -y skills add kensaurus/cursor-kenji --skill design-motion

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

One thing to look at

  • 6 stars6 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

What its author says it does

Copied from the file, not written here

Design and implement purposeful motion — micro-interactions, page transitions, scroll animations, and hover effects — using Framer Motion, CSS animations, and GSAP. Use when the user says "add animation", "make it feel alive", "micro-interaction", "page transition", "scroll animation", "hover effect", or "motion design". Outputs performance-safe, reduced-motion-aware animation code. Pairs with design-frontend, enhance-web-ui. Do NOT use for layout, typography, or purely functional UI work.

The file declares its own license as MIT. That is the author’s claim about this one file, and it is not the same thing as the license GitHub reports for the repository, which is listed with the other numbers below.

SKILL.md

7.5 KB, as published. Nobody here has run it

Motion Design Skill

Create purposeful, performant animations that enhance UX without overwhelming users.

CRITICAL: Check Existing First

Before adding ANY animation, verify:

  1. Check for existing animation utilities:
cat package.json | grep -i "framer-motion\|gsap\|animat"
rg "motion\.|animate\(|useSpring" --type tsx -l | head -10
  1. Check for existing CSS animations:
rg "@keyframes|animation:" --type css
cat tailwind.config.* | grep -A20 "animation\|keyframes"
  1. Check for animation preferences:
rg "prefers-reduced-motion" --type tsx --type css

Why: Maintain consistent animation language. Respect user motion preferences.

Animation Principles

1. Purpose-Driven Motion

Every animation should serve a purpose:

  • Feedback - Confirm user actions (button press, form submit)
  • Orientation - Show where elements come from/go to
  • Focus - Direct attention to important elements
  • Delight - Add personality (use sparingly)

2. Performance Rules

  • Use transform and opacity only (GPU-accelerated)
  • Avoid animating width, height, top, left (trigger layout)
  • Use will-change sparingly and remove after animation
  • Target 60fps - keep animations under 100ms for interactions

Framer Motion Patterns (React)

Basic Animations

import { motion } from 'framer-motion'

// Entrance animation
<motion.div
 initial={{ opacity: 0, y: 20 }}
 animate={{ opacity: 1, y: 0 }}
 transition={{ duration: 0.3, ease: "easeOut" }}
>
 Content
</motion.div>

// Exit animation
<motion.div
 exit={{ opacity: 0, scale: 0.95 }}
 transition={{ duration: 0.2 }}
>
 Content
</motion.div>

Hover & Tap Interactions

<motion.button
 whileHover={{ scale: 1.02, boxShadow: "0 4px 20px rgba(0,0,0,0.1)" }}
 whileTap={{ scale: 0.98 }}
 transition={{ type: "spring", stiffness: 400, damping: 17 }}
>
 Click me
</motion.button>

Staggered Lists

const container = {
 hidden: { opacity: 0 },
 show: {
 opacity: 1,
 transition: { staggerChildren: 0.05 }
 }
}

const item = {
 hidden: { opacity: 0, x: -20 },
 show: { opacity: 1, x: 0 }
}

<motion.ul variants={container} initial="hidden" animate="show">
 {items.map(i => (
 <motion.li key={i.id} variants={item}>{i.name}</motion.li>
 ))}
</motion.ul>

Scroll-Triggered Animations

import { motion, useScroll, useTransform } from 'framer-motion'

function ParallaxSection() {
 const { scrollYProgress } = useScroll()
 const y = useTransform(scrollYProgress, [0, 1], [0, -100])
 const opacity = useTransform(scrollYProgress, [0, 0.5, 1], [1, 1, 0])

 return (
 <motion.div style={{ y, opacity }}>
 Parallax content
 </motion.div>
 )
}

Page Transitions (Next.js)

// app/template.tsx
'use client'
import { motion } from 'framer-motion'

export default function Template({ children }: { children: React.ReactNode }) {
 return (
 <motion.div
 initial={{ opacity: 0, y: 10 }}
 animate={{ opacity: 1, y: 0 }}
 exit={{ opacity: 0, y: -10 }}
 transition={{ duration: 0.3 }}
 >
 {children}
 </motion.div>
 )
}

Layout Animations

// Shared layout animations
<motion.div layout layoutId="card">
 {isExpanded ? <ExpandedCard /> : <CollapsedCard />}
</motion.div>

// Smooth height changes
<motion.div
 layout
 transition={{ layout: { duration: 0.3 } }}
>
 {showMore && <AdditionalContent />}
</motion.div>

CSS-Only Animations

Tailwind Animations

// Fade in
<div className="animate-in fade-in duration-300">

// Slide up
<div className="animate-in slide-in-from-bottom-4 duration-500">

// Combined
<div className="animate-in fade-in slide-in-from-bottom-4 duration-500 delay-150">

// Custom in tailwind.config.ts
animation: {
 'float': 'float 3s ease-in-out infinite',
 'pulse-slow': 'pulse 3s ease-in-out infinite',
 'shimmer': 'shimmer 2s linear infinite',
}
keyframes: {
 float: {
 '0%, 100%': { transform: 'translateY(0)' },
 '50%': { transform: 'translateY(-10px)' },
 },
 shimmer: {
 '0%': { backgroundPosition: '-200% 0' },
 '100%': { backgroundPosition: '200% 0' },
 },
}

Loading Skeleton

<div className="animate-pulse space-y-4">
 <div className="h-4 bg-muted rounded w-3/4" />
 <div className="h-4 bg-muted rounded w-1/2" />
</div>

// Shimmer effect
<div className="relative overflow-hidden bg-muted rounded">
 <div className="absolute inset-0 -translate-x-full animate-shimmer bg-gradient-to-r from-transparent via-white/20 to-transparent" />
</div>

GSAP for Complex Animations

import { gsap } from 'gsap'
import { ScrollTrigger } from 'gsap/ScrollTrigger'
import { useGSAP } from '@gsap/react'

gsap.registerPlugin(ScrollTrigger)

function HeroSection() {
 const containerRef = useRef(null)

 useGSAP(() => {
 const tl = gsap.timeline({
 scrollTrigger: {
 trigger: containerRef.current,
 start: "top center",
 end: "bottom center",
 scrub: 1,
 }
 })

 tl.from(".hero-title", { opacity: 0, y: 100, duration: 1 })
 .from(".hero-subtitle", { opacity: 0, y: 50 }, "-=0.5")
 .from(".hero-cta", { opacity: 0, scale: 0.8 }, "-=0.3")
 }, { scope: containerRef })

 return <div ref={containerRef}>...</div>
}

Micro-Interactions Checklist

Buttons

  • Hover: subtle scale (1.02) + shadow
  • Active/tap: scale down (0.98)
  • Loading: spinner + disabled state
  • Success: checkmark animation
  • Focus: visible ring animation

Forms

  • Input focus: border color transition
  • Label float animation on focus
  • Error shake animation
  • Success checkmark
  • Submit button loading state

Navigation

  • Active indicator slides
  • Dropdown fade + slide
  • Mobile menu slide from edge
  • Breadcrumb transitions

Cards

  • Hover lift effect
  • Image zoom on hover
  • Content reveal on hover
  • Selection state pulse

Modals

  • Backdrop fade in
  • Content scale + fade
  • Exit animation before unmount

Accessibility

// Always respect reduced motion preference
const prefersReducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)').matches

// Framer Motion
<motion.div
 initial={prefersReducedMotion ? false : { opacity: 0 }}
 animate={{ opacity: 1 }}
 transition={{ duration: prefersReducedMotion ? 0 : 0.3 }}
>

// CSS
@media (prefers-reduced-motion: reduce) {
 *, *::before, *::after {
 animation-duration: 0.01ms !important;
 transition-duration: 0.01ms !important;
 }
}

// Tailwind
<div className="motion-safe:animate-bounce motion-reduce:animate-none">

Delight & gamification patterns

For playful interactions (bouncy buttons, magnetic elements, confetti, Konami code, satisfying toggles, progress milestones), see references/delight-interactions.md.

Validation

After implementing animations:

  1. Performance → 60fps in Chrome DevTools Performance tab
  2. Reduced motion → Test with prefers-reduced-motion: reduce
  3. Mobile → Test on actual device (not just emulator)
  4. Purpose → Each animation serves a clear UX purpose
  5. Consistency → Timing/easing matches rest of app

Keep looking

Skills are one crate of 328,083. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.