.cursor/skills/web-animation-design/SKILL.md
--- name: web-animation-design description: Design and implement web animations that feel natural and purposeful. Use this skill proactively whenever the user asks questions about animations, motion, easing, timing, duration, springs, transitions, or animation performance. This includes questions about how to animate specific UI elements, which easing to use, animation best practices, or accessibility considerations for motion. Triggers on: easing, ease-out, ease-in, ease-in-out, cubic-bezier, b
npx skillsauth add keystone-ui/react .cursor/skills/web-animation-designInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
A comprehensive guide for creating animations that feel right, based on Emil Kowalski's "Animations on the Web" course.
When this skill is first invoked without a specific question, respond only with:
I'm ready to help you with animations based on Emil Kowalski's animations.dev course.
Do not provide any other information until the user asks a question.
When reviewing animations, you MUST use a markdown table. Do NOT use a list with "Before:" and "After:" on separate lines. Always output an actual markdown table like this:
| Before | After |
| --------------------------------- | ----------------------------------------------- |
| transform: scale(0) | transform: scale(0.95) |
| animation: fadeIn 400ms ease-in | animation: fadeIn 200ms ease-out |
| No reduced motion support | @media (prefers-reduced-motion: reduce) {...} |
Wrong format (never do this):
Before: transform: scale(0)
After: transform: scale(0.95)
────────────────────────────
Before: 400ms duration
After: 200ms
Correct format: A single markdown table with | Before | After | columns, one row per issue.
Every animation decision starts with these questions:
ease-outease-in-outeaseUse for user-initiated interactions: dropdowns, modals, tooltips, any element entering or exiting the screen.
/* Sorted weak to strong */
--ease-out-quad: cubic-bezier(0.25, 0.46, 0.45, 0.94);
--ease-out-cubic: cubic-bezier(0.215, 0.61, 0.355, 1);
--ease-out-quart: cubic-bezier(0.165, 0.84, 0.44, 1);
--ease-out-quint: cubic-bezier(0.23, 1, 0.32, 1);
--ease-out-expo: cubic-bezier(0.19, 1, 0.22, 1);
--ease-out-circ: cubic-bezier(0.075, 0.82, 0.165, 1);
Why it works: Acceleration at the start creates an instant, responsive feeling. The element "jumps" toward its destination then settles in.
Use when elements already on screen need to move or morph. Mimics natural motion like a car accelerating then braking.
/* Sorted weak to strong */
--ease-in-out-quad: cubic-bezier(0.455, 0.03, 0.515, 0.955);
--ease-in-out-cubic: cubic-bezier(0.645, 0.045, 0.355, 1);
--ease-in-out-quart: cubic-bezier(0.77, 0, 0.175, 1);
--ease-in-out-quint: cubic-bezier(0.86, 0, 0.07, 1);
--ease-in-out-expo: cubic-bezier(1, 0, 0, 1);
--ease-in-out-circ: cubic-bezier(0.785, 0.135, 0.15, 0.86);
Use for hover states and color transitions. The asymmetrical curve (faster start, slower end) feels elegant for gentle animations.
transition: background-color 150ms ease;
Only use for:
Linear feels robotic and unnatural for interactive elements.
Avoid for UI animations. Makes interfaces feel sluggish because the slow start delays visual feedback.
Elements that animate together must use the same easing and duration. Modal + overlay, tooltip + arrow, drawer + backdrop—if they move as a unit, they should feel like a unit.
/* Both use the same timing */
.modal {
transition: transform 200ms ease-out;
}
.overlay {
transition: opacity 200ms ease-out;
}
| Element Type | Duration | | --------------------------------- | --------- | | Micro-interactions | 100-150ms | | Standard UI (tooltips, dropdowns) | 150-250ms | | Modals, drawers | 200-300ms |
Rules:
Determine how often users will see the animation:
Example: Raycast never animates because users open it hundreds of times a day.
Do animate:
Don't animate:
Marketing vs. Product:
Springs feel more natural because they don't have fixed durations—they simulate real physics.
Apple's approach (recommended):
// Duration + bounce (easier to understand)
{ type: "spring", duration: 0.5, bounce: 0.2 }
Traditional physics:
// Mass, stiffness, damping (more complex)
{ type: "spring", mass: 1, stiffness: 100, damping: 10 }
Springs maintain velocity when interrupted—CSS animations restart from zero. This makes springs ideal for gestures users might change mid-motion.
Only animate transform and opacity. These skip layout and paint stages, running entirely on the GPU.
Avoid animating:
padding, margin, height, width (trigger layout)blur filters above 20px (expensive, especially Safari)/* Force GPU acceleration */
.animated-element {
will-change: transform;
}
React-specific:
Framer Motion:
// Hardware accelerated (transform as string)
<motion.div animate={{ transform: "translateX(100px)" }} />
// NOT hardware accelerated (more readable)
<motion.div animate={{ x: 100 }} />
requestAnimationFrameAnimations can cause motion sickness or distraction for some users.
Whenever you add an animation, also add a media query to disable it:
.modal {
animation: fadeIn 200ms ease-out;
}
@media (prefers-reduced-motion: reduce) {
.modal {
animation: none;
}
}
prefers-reduced-motion media queryanimation: none or transition: none (no !important)import { useReducedMotion } from "framer-motion";
function Component() {
const shouldReduceMotion = useReducedMotion();
return (
<motion.div
initial={shouldReduceMotion ? false : { opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
/>
);
}
/* Disable hover animations on touch devices */
@media (hover: hover) and (pointer: fine) {
.element:hover {
transform: scale(1.05);
}
}
Touch devices trigger hover on tap, causing false positives.
Quick reference for common scenarios. See PRACTICAL-TIPS.md for detailed implementations.
| Scenario | Solution |
| ------------------------------- | ----------------------------------------------- |
| Make buttons feel responsive | Add transform: scale(0.97) on :active |
| Element appears from nowhere | Start from scale(0.95), not scale(0) |
| Shaky/jittery animations | Add will-change: transform |
| Hover causes flicker | Animate child element, not parent |
| Popover scales from wrong point | Set transform-origin to trigger location |
| Sequential tooltips feel slow | Skip delay/animation after first tooltip |
| Small buttons hard to tap | Use 44px minimum hit area (pseudo-element) |
| Something still feels off | Add subtle blur (under 20px) to mask it |
| Hover triggers on mobile | Use @media (hover: hover) and (pointer: fine) |
Is the element entering or exiting the viewport? ├── Yes → ease-out └── No ├── Is it moving/morphing on screen? │ └── Yes → ease-in-out └── Is it a hover change? ├── Yes → ease └── Is it constant motion? ├── Yes → linear └── Default → ease-out
development
Manages Keystone UI components and projects — adding, searching, fixing, debugging, styling, and composing UI built on Tailwind CSS v4 + Base UI. Provides project context, component docs, and usage examples. Applies when working with Keystone UI, @keystoneui/react, components.json with @keystoneui/* registries, or any project with @keystoneui/react in its dependencies. Also triggers for "keystoneui add", "find a Keystone UI example", or "switch to Keystone UI".
development
React and Next.js performance optimization guidelines from Vercel Engineering. This skill should be used when writing, reviewing, or refactoring React/Next.js code to ensure optimal performance patterns. Triggers on tasks involving React components, Next.js pages, data fetching, bundle optimization, or performance improvements.
development
Use this agent to create or update technical documentation for Keystone UI components, features, or guides. This includes Storybook stories in /apps/storybook/stories/ and (future) Fumadocs MDX documentation. The agent follows Keystone UI's documentation standards emphasizing brevity, accuracy, and practical code examples. Triggers on keywords like write documentation, create story, new component docs, write stories, document component, add storybook story, update docs, create guide.
development
Use this agent to review, improve, or curate documentation files for Keystone UI. This includes Storybook stories in /apps/storybook/stories/ and (future) MDX documentation. The agent verifies accuracy against component source, ensures completeness of variant/state coverage, improves code examples, and maintains consistency with Keystone UI patterns. Triggers on keywords like review stories, improve documentation, curate docs, audit stories, check documentation quality, story review, docs review.