eliasoulkadi/shokunin/motion-craft
Claude Code and agent skill by eliasoulkadi/shokunin
- community
Checking that the SKILL.md file is still in the repository.
Design GPU-accelerated animations with Web Animations API (WAAPI), Scroll-Driven Animations (ScrollTimeline/ViewTimeline), FLIP technique, easing systems, and accessibility (prefers-reduced-motion). Use when user asks to create animations, transitions, scroll effects, page transitions, or interactive motion for web UIs. Do NOT use for canvas-based animations (Three.js, PixiJS), video editing, or non-web (native mobile) motion design.
Install
npx vskill@latest install eliasoulkadi/shokunin/motion-craftSKILL.md
Motion Craft
Animations that communicate, not decorate. Every frame must earn its place.
Inspired by Emil Kowalski (Linear, Sonner, Vaul), Paul Lewis (Google Chrome), and the CSS Animation Working Group.
Workflow
The Animation Decision Framework
Before writing any animation code, answer these four questions in order.
1. Should this animate at all?
| Frequency | Decision | Reason | |
|---|---|---|---|
| 100+ times/day (keyboard shortcuts, command palette, search toggle) | No animation. Ever. | Animation makes frequent actions feel delayed. Raycast has no open/close animation. Optimal. | |
| Tens of times/day (hover effects, list navigation) | Remove or drastically reduce | Users notice animation latency on repeated interactions | |
| Occasional (modals, drawers, toasts) | Standard animation | The right place for motion | |
| Rare / first-time (onboarding, confirmation, celebration) | Add delight | These moments earn longer, richer animations |
Never animate keyboard-initiated actions. These repeat hundreds of times daily.
2. What is the purpose?
Every animation must have a clear answer to "why does this animate?"
| Purpose | Example | Valid? | |
|---|---|---|---|
| Spatial consistency | Toast enters and exits from the same direction | ? | |
| State indication | Button morphs to show "sent" | ? | |
| Feedback | Button scales down on press, confirming the interface heard the user | ? | |
| Preventing jarring changes | Elements fading in instead of appearing abruptly | ? | |
| Explanation | Marketing animation showing how a feature works | ? | |
| "It looks cool" AND the user sees it often | Gratuitous motion | ? |
3. What easing should it use?
| Scenario | Easing | CSS | |
|---|---|---|---|
| Element entering | ease-out (starts fast, feels responsive) | cubic-bezier(0, 0, 0.2, 1) | |
| Element exiting | ease-in (starts slow, grabs attention briefly then accelerates away) | cubic-bezier(0.4, 0, 1, 1) | |
| On-screen movement / morphing | ease-in-out | cubic-bezier(0.4, 0, 0.2, 1) | |
| Hover / color change | ease | cubic-bezier(0.25, 0.1, 0.25, 1) | |
| Constant motion (marquee, progress bar) | linear | cubic-bezier(0, 0, 1, 1) | |
| UI interactions (buttons, tooltips, dropdowns) | strong ease-out | cubic-bezier(0.23, 1, 0.32, 1) |
Critical: never use ease-in for UI entering animations. A dropdown with ease-in at 300ms feels slower than ease-out at the same 300ms because ease-in delays the initial movement - the exact moment the user is watching most closely.
4. How fast should it be?
| Element | Duration | Easing | |
|---|---|---|---|
| Button press feedback (scale) | 100-160ms | cubic-bezier(0.23, 1, 0.32, 1) | |
| Tooltip enter / exit | 125-200ms | cubic-bezier(0.23, 1, 0.32, 1) | |
| Dropdown / select / popover | 150-250ms | cubic-bezier(0.23, 1, 0.32, 1) | |
| Hover transform (scale, lift) | 200ms | cubic-bezier(0.23, 1, 0.32, 1) | |
| Modal / dialog enter | 200-300ms | cubic-bezier(0, 0, 0.2, 1) | |
| Modal / dialog exit | 150-200ms | cubic-bezier(0.4, 0, 1, 1) | |
| Drawer / sheet enter | 200-400ms | cubic-bezier(0.32, 0.72, 0, 1) (iOS-like) | |
| Toast enter | 300-400ms | cubic-bezier(0.23, 1, 0.32, 1) | |
| Toast exit | 200-300ms | cubic-bezier(0.4, 0, 1, 1) | |
| Page transition | 300-400ms | cubic-bezier(0.4, 0, 0.2, 1) | |
| Scroll reveal (fade + slide up) | 400-800ms | cubic-bezier(0.16, 1, 0.3, 1) | |
| Loading shimmer | 1000-1500ms (infinite) | linear | |
| Hold-to-delete (press) | 2000ms | linear (deliberate) | |
| Hold-to-delete (release) | 200ms | cubic-bezier(0.23, 1, 0.32, 1) (snappy) | |
| Marketing / explanatory | 800-3000ms | variable, depends on narrative |
Rule: UI animations should stay under 300ms. A 180ms dropdown feels noticeably more responsive than a 400ms one.
Custom easing curves
The built-in CSS ease / ease-in / ease-out are too weak. Use these stronger custom variants:
Sources: easing.dev, easings.co
The 60fps Golden Rule
16.67ms per frame. Verify with Chrome DevTools Performance tab. Only animate transform and opacity.
| Property | GPU composite? | Triggers | |
|---|---|---|---|
transform (translate, scale, rotate) | ? Yes | Composite only | |
opacity | ? Yes | Composite only | |
filter | ?? Sometimes | Paint + Composite | |
clip-path | ?? Sometimes | Paint + Composite | |
width, height, top, left, margin, padding, border-width | ? No | Layout + Paint + Composite | |
box-shadow | ? No | Paint + Composite | |
color, background-color | ? No | Paint only |
Review Format (Required)
When reviewing UI animation code, you MUST use a markdown table with Before | After | Why columns. Do NOT use a list with "Before:" and "After:" on separate lines.
Correct format:
| Before | After | Why | |
|---|---|---|---|
transition: all 300ms | transition: transform 200ms ease-out | Specify exact properties; avoid all which triggers layout recalculation | |
transform: scale(0) | transform: scale(0.95); opacity: 0 | Nothing in the real world appears from nothing | |
ease-in on dropdown | cubic-bezier(0.23, 1, 0.32, 1) | ease-in starts slow - feels sluggish. Strong ease-out gives instant feedback | |
No :active state on button | transform: scale(0.97) on :active | Buttons must feel responsive to press | |
transform-origin: center on popover | transform-origin: var(--radix-popover-content-transform-origin) | Popovers should scale from their trigger. Modals stay centered. | |
transition: 300ms without prefers-reduced-motion | @media (prefers-reduced-motion: reduce) { transition-duration: 0.01ms } | WCAG 2.1 requires reduced-motion support | |
animate={{ x: 100 }} in Framer Motion | animate={{ transform: "translateX(100px)" }} | Framer Motion x/y are NOT hardware-accelerated. Use transform string for GPU. |
Wrong format (never do this):
CSS Transitions (preferred for UI)
CSS transitions are interruptible - they can be retargeted mid-animation. Keyframes restart from zero. For any interaction that can be triggered rapidly (toasts, toggles, dropdowns), transitions produce smoother results.
Asymmetric enter / exit timing
Enter can be slower (user is deciding), exit must be fast (system responding):
Tooltips: skip delay on subsequent hovers
Enter states with @starting-style (Chrome-only as of 2026, not yet Baseline)
Note:@starting-styleand scroll-driven animations (animation-timeline: view(),animation-timeline: scroll()) are Chrome-only as of 2026. Use JavaScript fallbacks for cross-browser support.
Hold-to-delete pattern
BUTTONS - Tactile Feedback
Every pressable element needs physical response.
The scale must be subtle (0.95-0.98). Applied to all pressable elements - buttons, cards, list items, tabs.
POPOVERS - Origin-Aware
Popovers scale from their trigger, not center. Modals stay centered.
Whether the user notices individually does not matter. In the aggregate, unseen details compound.
Stagger Animations
When multiple elements enter together, stagger their appearance.
Keep stagger delays short (30-80ms between items). Never block interaction while stagger plays.
CSS Animations (keyframes)
Use for predetermined, non-dynamic animations. Keyframes restart from zero on interruption - avoid for UI.
Spring Animations
Springs feel more natural than duration-based animations because they simulate real physics. They maintain velocity when interrupted.
When to use springs
- Drag interactions with momentum
- Elements that feel "alive" (Apple Dynamic Island style)
- Gestures that can be interrupted mid-animation
- Decorative mouse-tracking interactions
Apple approach (recommended - easier to reason about)
Traditional physics (more control)
Keep bounce subtle (0.1-0.3). Avoid bounce in most UI. Use for drag-to-dismiss and playful interactions only.
Spring-based mouse interactions
Without spring: feels artificial, instant. With spring: feels natural, has momentum.
WEB ANIMATIONS API (WAAPI)
Programmatic CSS animations. Hardware-accelerated, interruptible, no library needed.
WAAPI beats Framer Motion under heavy load - it runs off the main thread. Use for dynamic, interruptible animations where CSS keyframes fall short.
SCROLL-DRIVEN ANIMATIONS
This is the start of the file. Read the full SKILL.md on GitHub.
Security
- Security scanPassed, 100 of 100Pattern checks on the skill's files.
- Model reviewNot runA model review is scheduled for the next rescan.
Quality evaluation
- Task evaluationNot runNo evaluation yet. Run one in Skill Studio.
Source
- SKILL.md in the repositoryChecking.pack/skills/motion-craft/SKILL.md
Popularity
- Repository stars
- 112
- Repository forks
- 14
- 7-day trend score
- 24
Stars and forks are for the whole GitHub repository, not this skill alone. Refreshed 27 Aug 2026, 2 months ago.
Works with
Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.
- Claude Code
- Cursor
- GitHub Copilot
- Windsurf
- Codex
- Gemini CLI
- Cline
- Amp
- Roo Code
- Goose
- Continue
- Kilo Code
- Junie
- Trae
- OpenHands
- Qwen Code
- AI Agent
- Tabnine Chat
- Sourcegraph Cody
- Amazon Q
- Firebase Genkit
- Sweep
- Devin
- Phind
- Mentat
- Claude Desktop
- Aider
- GPT Pilot
- Plandex
- bolt.new
- v0
- Replit Agent
- Anse
- TypingMind
- BetterChatGPT
- LibreChat
- Warp AI
- Pieces
- Fig AI
Embed badge
[](https://verified-skill.com/skills/eliasoulkadi/shokunin/motion-craft)