Agent skill

Motion Craft

by EliasOulkadi in EliasOulkadi/shokunin

Design GPU-accelerated animations with Web Animations API (WAAPI), Scroll-Driven Animations (ScrollTimeline/ViewTimeline), FLIP technique, easing systems, and accessibility (prefers-reduced-motion).

MITAuto-check passedFrontend & Design

Install Motion Craft

skills CLI
$ npx skills add EliasOulkadi/shokunin --skill motion-craft -a claude-code

Project install by default; add -g for ~/.claude/skills/.

GitHub CLI
$ gh skill install EliasOulkadi/shokunin motion-craft --agent claude-code

Project scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).

Manual copy
$ git clone --depth 1 https://github.com/EliasOulkadi/shokunin.git skills-src && mkdir -p .claude/skills && cp -r skills-src/.pack/skills/motion-craft .claude/skills/motion-craft && rm -rf skills-src

Use ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.

Claude Code skills documentation · loads skills from .claude/skills/

Facts

Skill name
motion-craft
GitHub stars
114
Token cost
~6.4k tokens
SKILL.md length
2,236 words
Files
5 (incl. scripts, references, assets)
Skills in repo
49
Repo updated
First seen
Licence
MIT

At a glance

Design GPU-accelerated animations with Web Animations API (WAAPI), Scroll-Driven Animations (ScrollTimeline/ViewTimeline), FLIP technique, easing systems, and accessibility (prefers-reduced-motion).

  • Works in 4 steps: Should this animate at all? → What is the purpose? → What easing should it use? → …
  • User asks to create animations
  • SKILL.md covers Workflow, The Animation Decision Framework, The 60fps Golden Rule and Review Format (Required), plus 8 more sections
  • Runs Shell scripts from its folder

What it does

Motion Craft is an agent skill from EliasOulkadi/shokunin. 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.

Its SKILL.md is about 6.4k tokens, which your agent loads only when the skill is triggered. The skill folder holds 7 other files, including scripts, reference files and assets (for example `references/animation-frameworks.md`, `references/motion-design-tokens.md` and `scripts/generate-easing.sh`). Compatibility notes: opencode

It sits in Frontend & Design, covering Web animation and motion, Video production and Motion graphics. It works with Three.js. The repository describes itself as: 職人 Shokunin 62 AI agent skills for OpenCode, Claude Code, Cursor, Windsurf. ChromaDB memory, MCP servers, declarative self-updates. Multi-model, open source, zero cost. The licence is MIT.

When your agent uses it

  • User asks to create animations
  • Page transitions
  • Interactive motion for web UIs
  • Canvas-based animations (Three.js

Example prompts

  • “/motion-craft”

Requirements

  • A Bash shell
  • Compatibility (from SKILL.md): opencode

Workflow steps

4 steps, taken from the step headings in SKILL.md.

  1. Should this animate at all?
  2. What is the purpose?
  3. What easing should it use?
  4. How fast should it be?

What it can do on your machine

Read from SKILL.md and the folder at commit 4c68e5b. It shows what the files ask for, not the result of running them.

  • Tool permissions

    Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.

    From allowed-tools in the SKILL.md frontmatter.

  • Runs code

    Ships 1 file in scripts/ (Shell), which the agent can run.

    From the folder's file list and the shell code blocks in SKILL.md.

  • Network

    Links to these hosts (documentation or services it may open):

    • easing.dev
    • easings.co

    From URLs in SKILL.md, links to its own repository left out.

  • Credentials

    Names no API keys, tokens, secrets or passwords.

    From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.

  • Compatibility

    opencode

    From compatibility in the SKILL.md frontmatter.

Context cost

Motion Craft loads about 6.4k tokens when it runs, and up to ~9.4k if it reads all its reference files. Until then it costs about 113 tokens; SKILL.md has 2,236 words of instructions outside code blocks.

Always · name and description, kept in context so the agent knows when to use it
~113
When it runs · the whole SKILL.md, loaded when a task matches
~6.4k
With references · SKILL.md plus every file in references/, read only if the agent opens them
~9.4k

Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.

Safety

Auto-check passed

The automated check found no risky patterns in SKILL.md.

Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); the scripts in this folder are not scanned.

SKILL.md

The full file from EliasOulkadi/shokunin at commit 4c68e5b, republished under its MIT licence (© EliasOulkadi). 2,236 words, ~6,405 tokens.

Download SKILL.mdSave it as .claude/skills/motion-craft/SKILL.md (or your agent's skills folder). This skill also uses 4 other files; get the full folder from GitHub.
name
motion-craft
description
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.
compatibility
opencode
triggers
animation, transition, motion, scroll animation, page transition, WAAPI, Web Animations API, scroll-driven animation, FLIP animation, easing, animate, spring…
negatives
Three.js, canvas animation, video editing, native mobile animation, game animation, CSS only
license
MIT
metadata.workflow
frontend
metadata.audience
developers
metadata.version
4.0.0
metadata.author
shokunin

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?
FrequencyDecisionReason
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 reduceUsers notice animation latency on repeated interactions
Occasional (modals, drawers, toasts)Standard animationThe right place for motion
Rare / first-time (onboarding, confirmation, celebration)Add delightThese 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?"

PurposeExampleValid?
Spatial consistencyToast enters and exits from the same direction?
State indicationButton morphs to show "sent"?
FeedbackButton scales down on press, confirming the interface heard the user?
Preventing jarring changesElements fading in instead of appearing abruptly?
ExplanationMarketing animation showing how a feature works?
"It looks cool" AND the user sees it oftenGratuitous motion?
3. What easing should it use?
ScenarioEasingCSS
Element enteringease-out (starts fast, feels responsive)cubic-bezier(0, 0, 0.2, 1)
Element exitingease-in (starts slow, grabs attention briefly then accelerates away)cubic-bezier(0.4, 0, 1, 1)
On-screen movement / morphingease-in-outcubic-bezier(0.4, 0, 0.2, 1)
Hover / color changeeasecubic-bezier(0.25, 0.1, 0.25, 1)
Constant motion (marquee, progress bar)linearcubic-bezier(0, 0, 1, 1)
UI interactions (buttons, tooltips, dropdowns)strong ease-outcubic-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?
ElementDurationEasing
Button press feedback (scale)100-160mscubic-bezier(0.23, 1, 0.32, 1)
Tooltip enter / exit125-200mscubic-bezier(0.23, 1, 0.32, 1)
Dropdown / select / popover150-250mscubic-bezier(0.23, 1, 0.32, 1)
Hover transform (scale, lift)200mscubic-bezier(0.23, 1, 0.32, 1)
Modal / dialog enter200-300mscubic-bezier(0, 0, 0.2, 1)
Modal / dialog exit150-200mscubic-bezier(0.4, 0, 1, 1)
Drawer / sheet enter200-400mscubic-bezier(0.32, 0.72, 0, 1) (iOS-like)
Toast enter300-400mscubic-bezier(0.23, 1, 0.32, 1)
Toast exit200-300mscubic-bezier(0.4, 0, 1, 1)
Page transition300-400mscubic-bezier(0.4, 0, 0.2, 1)
Scroll reveal (fade + slide up)400-800mscubic-bezier(0.16, 1, 0.3, 1)
Loading shimmer1000-1500ms (infinite)linear
Hold-to-delete (press)2000mslinear (deliberate)
Hold-to-delete (release)200mscubic-bezier(0.23, 1, 0.32, 1) (snappy)
Marketing / explanatory800-3000msvariable, 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:

css
:root {
  --ease-out-strong: cubic-bezier(0.23, 1, 0.32, 1);     /* UI interactions, Emil's signature */
  --ease-in-out-strong: cubic-bezier(0.77, 0, 0.175, 1);  /* On-screen movement */
  --ease-drawer: cubic-bezier(0.32, 0.72, 0, 1);          /* iOS-like drawer */
  --ease-out-expo: cubic-bezier(0.16, 1, 0.3, 1);         /* Slow reveals, dramatic */
  --ease-out-quint: cubic-bezier(0.22, 1, 0.36, 1);       /* Alternative strong ease-out */
  --ease-spring: cubic-bezier(0.34, 1.56, 0.64, 1);       /* Slight overshoot, sparingly */
}

Sources: easing.dev, easings.co


The 60fps Golden Rule

16.67ms per frame. Verify with Chrome DevTools Performance tab. Only animate transform and opacity.

PropertyGPU composite?Triggers
transform (translate, scale, rotate)? YesComposite only
opacity? YesComposite only
filter?? SometimesPaint + Composite
clip-path?? SometimesPaint + Composite
width, height, top, left, margin, padding, border-width? NoLayout + Paint + Composite
box-shadow? NoPaint + Composite
color, background-color? NoPaint 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:
BeforeAfterWhy
transition: all 300mstransition: transform 200ms ease-outSpecify exact properties; avoid all which triggers layout recalculation
transform: scale(0)transform: scale(0.95); opacity: 0Nothing in the real world appears from nothing
ease-in on dropdowncubic-bezier(0.23, 1, 0.32, 1)ease-in starts slow - feels sluggish. Strong ease-out gives instant feedback
No :active state on buttontransform: scale(0.97) on :activeButtons must feel responsive to press
transform-origin: center on popovertransform-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 Motionanimate={{ transform: "translateX(100px)" }}Framer Motion x/y are NOT hardware-accelerated. Use transform string for GPU.

Wrong format (never do this):

Before: transition: all 300ms
After: transition: transform 200ms ease-out

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.

css
.button {
  transition: transform 160ms ease-out;
}
.button:active {
  transform: scale(0.97);
}

.tooltip {
  transition: transform 125ms ease-out, opacity 125ms ease-out;
  transform-origin: var(--transform-origin);
}
Asymmetric enter / exit timing

Enter can be slower (user is deciding), exit must be fast (system responding):

css
.overlay {
  transition: clip-path 200ms ease-out;  /* release: fast */
}
.button:active .overlay {
  transition: clip-path 2s linear;       /* press: slow and deliberate */
}
Tooltips: skip delay on subsequent hovers
css
.tooltip {
  transition: transform 125ms ease-out, opacity 125ms ease-out;
  transform-origin: var(--transform-origin);
}
.tooltip[data-instant] {
  transition-duration: 0ms;
}
Enter states with @starting-style (Chrome-only as of 2026, not yet Baseline)
css
.toast {
  opacity: 1;
  transform: translateY(0);
  transition: opacity 400ms ease-out, transform 400ms ease-out;

  @starting-style {
    opacity: 0;
    transform: translateY(100%);
  }
}

Note: @starting-style and 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
css
.overlay {
  clip-path: inset(0 100% 0 0);
  transition: clip-path 200ms ease-out;   /* release: fast */
}
.button:active .overlay {
  clip-path: inset(0 0 0 0);
  transition: clip-path 2s linear;        /* press: slow and deliberate */
}

BUTTONS - Tactile Feedback

Every pressable element needs physical response.

css
.button {
  transition: transform 160ms cubic-bezier(0.23, 1, 0.32, 1);
}
.button:active {
  transform: scale(0.97);
}

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.

css
/* Radix UI */
.popover {
  transform-origin: var(--radix-popover-content-transform-origin);
}
/* Base UI */
.popover {
  transform-origin: var(--transform-origin);
}
/* Modals (always centered) */
.modal {
  transform-origin: center;
}

Whether the user notices individually does not matter. In the aggregate, unseen details compound.


Stagger Animations

When multiple elements enter together, stagger their appearance.

css
.item {
  opacity: 0;
  transform: translateY(8px);
  animation: fadeIn 300ms ease-out forwards;
}
.item:nth-child(1) { animation-delay: 0ms; }
.item:nth-child(2) { animation-delay: 50ms; }
.item:nth-child(3) { animation-delay: 100ms; }
.item:nth-child(4) { animation-delay: 150ms; }

@keyframes fadeIn {
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

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.

css
@keyframes enter-right {
  from { opacity: 0; transform: translateX(16px); }
  to   { opacity: 1; transform: translateX(0); }
}
.enter {
  animation: enter-right 300ms ease-out forwards;
}

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
js
{ type: "spring", duration: 0.5, bounce: 0.2 }
Traditional physics (more control)
js
{ type: "spring", stiffness: 100, damping: 10, mass: 1 }

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
jsx
import { useSpring } from 'framer-motion'

const springX = useSpring(mouseX * 0.1, { stiffness: 100, damping: 10 })

Without spring: feels artificial, instant. With spring: feels natural, has momentum.


WEB ANIMATIONS API (WAAPI)

Programmatic CSS animations. Hardware-accelerated, interruptible, no library needed.

javascript
const element = document.querySelector('.card')

const animation = element.animate([
  { transform: 'scale(1)', opacity: 1 },
  { transform: 'scale(0.95)', opacity: 0.7 },
], {
  duration: 200,
  easing: 'cubic-bezier(0.23, 1, 0.32, 1)',
  fill: 'both',
})

animation.pause()
animation.play()
animation.reverse()
animation.finish()
animation.finished.then(() => console.log('done'))

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

Browser support note: Scroll-driven animations (animation-timeline: view() and scroll()) are Chrome/Edge-only as of 2026, not yet Baseline. Provide JS fallbacks via IntersectionObserver for Firefox/Safari.

ViewTimeline (element enters/leaves viewport)
css
@keyframes fade-up {
  from { opacity: 0; transform: translateY(20px); }
  to   { opacity: 1; transform: translateY(0); }
}
.reveal {
  animation: fade-up 600ms linear both;
  animation-timeline: view();
  animation-range: entry 0% entry 100%;
}
ScrollTimeline (page scroll position)
css
@keyframes shrink {
  from { height: 80px; }
  to   { height: 50px; }
}
.site-header {
  animation: shrink 300ms linear both;
  animation-timeline: scroll();
  animation-range: 0 200px;
}
Scroll-linked parallax (vanilla JS)
js
const layers = document.querySelectorAll('[data-parallax]')
window.addEventListener('scroll', () => {
  const scrollY = window.scrollY
  layers.forEach(layer => {
    const speed = parseFloat(layer.dataset.parallax) || 0.3
    layer.style.transform = `translateY(${scrollY * speed}px)`
  })
})

FLIP Technique

For layout animations - animating elements that change position/size.

javascript
function animateLayout(element, callback) {
  const first = element.getBoundingClientRect()
  callback()
  const last = element.getBoundingClientRect()

  const dx = first.left - last.left
  const dy = first.top - last.top
  const dw = first.width / last.width
  const dh = first.height / last.height

  element.animate([
    { transform: `translate(${dx}px, ${dy}px) scale(${dw}, ${dh})` },
    { transform: 'translate(0, 0) scale(1, 1)' },
  ], {
    duration: 300,
    easing: 'cubic-bezier(0.4, 0, 0.2, 1)',
  })
}

CLIP-PATH for Animation

One of the most powerful animation tools in CSS. Hardware-accelerated.

css
.overlay {
  clip-path: inset(0 100% 0 0);
  transition: clip-path 200ms ease-out;
}
.visible {
  clip-path: inset(0 0 0 0);
}

Use for: hold-to-delete, image reveals on scroll, comparison sliders, seamless color transitions on tabs.


PERCEIVED PERFORMANCE

Speed in animation directly affects how users perceive your app:

EffectMechanism
Fast-spinning spinnerMakes loading feel faster (same load time, different perception)
180ms select vs 400ms selectShorter animation = perceived responsiveness jump
Instant tooltips after first oneSkip delay + animation on subsequent tooltips
Fast exit animationsExit must be faster than enter (200ms enter, 150ms exit)
ease-out vs ease-in at same 200msease-out feels faster because user sees immediate movement

PERFORMANCE RULES

Only animate transform and opacity

These skip layout and paint, running on GPU.

CSS variables are inheritable - avoid for animation
js
// Bad: triggers recalculation on all children
element.style.setProperty('--swipe-amount', `${distance}px`)

// Good: only affects this element
element.style.transform = `translateY(${distance}px)`
CSS animations beat JS under load

When the browser is busy loading a new page, Framer Motion animations (using requestAnimationFrame) drop frames. CSS animations remain smooth - they run off the main thread.

Framer Motion: use transform string, not shorthand
jsx
// NOT hardware accelerated (requestAnimationFrame on main thread)
<motion.div animate={{ x: 100 }} />

// Hardware accelerated (GPU, stays smooth even under load)
<motion.div animate={{ transform: "translateX(100px)" }} />
will-change: use sparingly
css
.will-animate {
  will-change: transform, opacity;
}

Each will-change creates a new compositor layer, consuming GPU memory. Apply before animation, remove after.


ACCESSIBILITY

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

WCAG 2.1 Success Criterion 2.3.3 - Animation from Interactions.

For fine-grained control:

javascript
const prefersReduced = window.matchMedia('(prefers-reduced-motion: reduce)').matches
const userPrefersReduced = localStorage.getItem('reduced-motion') === 'true'
const shouldReduce = prefersReduced || userPrefersReduced
Touch device hover states
css
@media (hover: hover) and (pointer: fine) {
  .element:hover { transform: scale(1.05); }
}

Touch devices trigger hover on tap. Gate hover animations behind this media query.


DEBUGGING ANIMATIONS

Slow motion testing

Play animations at reduced speed to spot issues invisible at full speed. Temporarily increase duration to 2-5x normal, or use browser DevTools animation inspector.

Things to look for:

  • Do colors transition smoothly, or do you see two distinct states overlapping?
  • Does the easing feel right, or does it start/stop abruptly?
  • Is the transform-origin correct?
  • Are multiple animated properties (opacity, transform, color) in sync?
Frame-by-frame inspection

Chrome DevTools Animations panel. Step frame by frame. Reveals timing issues between coordinated properties invisible at full speed.

Show full SKILL.md (900 more words)Show less
Test on real devices

For touch interactions (drawers, swipe gestures), test on physical devices. Connect phone via USB, visit local dev server by IP address, use Safari remote devtools.


REVIEW CHECKLIST

IssueFix
transition: allSpecify exact properties: transition: transform 200ms ease-out
scale(0) entry animationStart from scale(0.95) with opacity: 0
ease-in on UI elementSwitch to strong ease-out or custom curve
transform-origin: center on popoverSet to trigger location (modals exempt)
Animation on keyboard actionRemove entirely
Duration > 300ms on UI elementReduce to 150-250ms
Hover animation without media queryAdd @media (hover: hover) and (pointer: fine)
Keyframes on rapidly-triggered elementUse CSS transitions for interruptibility
Framer Motion x/y props under loadUse transform: "translateX()"
Same enter/exit transition speedExit must be faster (e.g. enter 2s, exit 200ms)
Elements all appear at onceStagger with 30-80ms between items
No prefers-reduced-motion fallbackRequired by WCAG 2.1
will-change left on after animationRemove or set to auto when done
JS scroll listeners for scroll effectsUse ViewTimeline / IntersectionObserver
CSS ease defaultReplace with custom cubic-bezier

PRE-FLIGHT CHECKLIST

Before delivering animated UI code:

  • No animation on keyboard-initiated actions
  • Every animation has a stated purpose (why does this animate?)
  • Easing curve matches scenario (entering ? ease-out, exiting ? ease-in)
  • UI duration under 300ms (button 100-160ms, dropdown 150-250ms, modal 200-300ms)
  • Exit faster than enter (asymmetric timing)
  • Only transform and opacity animated (GPU composite)
  • prefers-reduced-motion respected
  • Hover animations gated behind @media (hover: hover)
  • Touch targets 44x44mm minimum
  • No scale(0) entries - start from scale(0.95)
  • Popover transform-origin anchors to trigger
  • Stagger delays under 80ms
  • No transition: all - exact properties only
  • Framer Motion: transform string over x/y shorthand
  • will-change removed after animation completes
  • Button press: scale(0.97) on :active
  • Tested on real device for touch interactions

Anti-Patterns

BANNED PATTERNS

BannedBecause
transition: allTriggers layout recalculation on every frame
ease-in on entering UIDelays initial movement - feels sluggish
scale(0) entryNothing disappears and reappears completely in the real world
Animating width, height, top, leftLayout thrashing - use transform
requestAnimationFrame for scroll effectsBlocking - use ScrollTimeline or IntersectionObserver
Bounce / elastic easing on functional UIUnprofessional - reserve for playful interactions only
Duration > 500ms on functional UIFeels slow - users notice and get frustrated
Auto-playing carousels without pauseWCAG accessibility violation
Framer Motion x/y props under loadNot hardware-accelerated - frames drop during page loads
No prefers-reduced-motionWCAG 2.1 failure
will-change on everythingGPU memory waste - creates compositor layers
translateZ(0) on every elementToo many GPU layers - memory overhead
Keyframes for dynamic UINot interruptible - use CSS transitions
transform-origin: center on popoversBreaks spatial consistency with trigger
Same speed enter and exitExit should always be faster

Error Handling

ErrorCauseFix
transition: all causes jank on unrelated property changesBrowser recalculates layout for every animated frame; all triggers layout on properties that don't need itSpecify exact properties: transition: transform 200ms ease-out, opacity 200ms ease-out
Framer Motion x/y props drop frames during page loadsx/y use requestAnimationFrame on the main thread, competing with React rendersUse animate={{ transform: "translateX(100px)" }} string — hardware-accelerated, GPU composite
Animation stutters on mobile SafariiOS Safari throttles requestAnimationFrame in low-power mode; non-composited properties force layoutOnly animate transform and opacity. Test on physical iOS devices via USB remote debugging.
Popover scales from wrong originDefault transform-origin: center breaks spatial consistency with the trigger elementSet transform-origin: var(--radix-popover-content-transform-origin) for Radix; var(--transform-origin) for Base UI
Staggered list items flash all at once then disappearanimation-delay applied but items are visible by default before animation startsSet initial state: opacity: 0; transform: translateY(8px). Animation resolves to visible.
CSS keyframes restart on re-trigger instead of continuingKeyframes run from frame 0 every time animation-name is appliedUse CSS transitions for interruptible UI (toasts, toggles, dropdowns). Keyframes only for predetermined, fire-once animations.
@starting-style doesn't work in Firefox/Safari@starting-style is Chrome-only as of 2026, not yet BaselineProvide JS fallback: set initial inline styles, then remove them on next frame to trigger transition.
Scroll-driven animation has no effect in Firefoxanimation-timeline: view() and scroll() are not supported outside Chrome/EdgeProvide IntersectionObserver fallback that toggles a CSS class for animation.
will-change: transform never removedBrowser allocates GPU memory for the compositor layer indefinitelyRemove will-change or set to auto after animation completes. Use sparingly — each layer costs GPU memory.
Magnetic button causes continuous React re-rendersuseState for cursor position triggers re-render at 60fpsUse Framer Motion useMotionValue + useTransform — updates outside React render cycle.
Scroll parallax jank from scroll event listenerwindow.addEventListener('scroll') fires on main thread, competing with renderingUse ScrollTimeline (Chrome) or throttled IntersectionObserver with requestAnimationFrame debounce.
Touch device fires hover state on tap, then hover state persistsMobile browsers synthesize hover on first tap and keep it until another tap elsewhereGate hover animations behind @media (hover: hover) and (pointer: fine).
Auto-playing carousel without pause buttonWCAG 2.2.2 violation: moving content must be pausableAdd pause/play button. Respect prefers-reduced-motion. Allow keyboard control.

Checklist

  • Animation uses compositor-only properties (transform, opacity) where possible
  • prefers-reduced-motion respected — fallback to static or reduced variant
  • Easing curve appropriate for the motion type (spring for UI, ease for enter/exit)
  • Before/After states compared — animation solves a real UX problem
  • Tested on mobile and with throttled CPU to verify 60fps

Sources

  • Emil Kowalski - animations.dev, Sonner, Vaul (Linear team)
  • Paul Lewis - "Stick to compositor-only properties" (Google Chrome)
  • Web Animations API Specification (W3C)
  • CSS Scroll-Driven Animations Specification (W3C)
  • WCAG 2.1 Guideline 2.3.3 - Animation from Interactions
  • easing.dev, easings.co - custom easing curve builders
  • motion.dev - Animation reference
  • Framer Motion documentation

© EliasOulkadi, MIT. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file

Files

SKILL.md and 4 other files (scripts, references, assets) in .pack/skills/motion-craft of EliasOulkadi/shokunin.

  • SKILL.md
  • assets/keyframes.css
  • references/animation-frameworks.md
  • references/motion-design-tokens.md
  • scripts/generate-easing.sh

Open the folder on GitHubat commit 4c68e5b

Compare with similar skills

Motion Craft next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.

Motion Craft compared with similar skills
SkillStarsUsed inTokensAuto-checkLicenceRepo updated
Motion Craft this skillEliasOulkadi/shokunin114—~6.4kAutomated safety check: PassMIT
Guizang Product Video Skillop7418/guizang-product-video-skill753—~1.1kAutomated safety check: PassAGPL-3.0
Oma Designfirst-fluke/oh-my-agent1.3k—~2.9kAutomated safety check: PassMIT
Motion DesignWrongStack/WrongStack371—~852Automated safety check: PassMIT
HyperFrames Animationheygen-com/hyperframes60k3 repos~2.1kAutomated safety check: PassApache-2.0
Phantom Motionpixelxzen/phantom-motion185—~1kAutomated safety check: PassApache-2.0

Similar skills

  • Guizang Product Video Skill

    op7418/guizang-product-video-skill

    制作代码驱动的软件产品宣传片和版本更新片(product promo、release notes video、changelog promo)。从真实功能和产品设计出发定方向,用真实组件、GSAP/Three.js 动效、原创配乐和动作音效完成影片,每支片子的视觉手法都从产品本身推导,不套模板。

    753 GitHub stars~1.1k tokensUpdated 2 days ago
    DevelopmentAuto-check passed
  • Oma Design

    first-fluke/oh-my-agent

    AI design specialist skill with DESIGN.md management, anti-pattern enforcement, optional Stitch MCP integration, and component library guidance.

    1.3k GitHub stars~2.9k tokensUpdated yesterday
    Frontend & DesignAuto-check passed
  • Motion Design

    WrongStack/WrongStack

    Implement web and React animation, gesture feedback, layout transitions and scroll sequences.

    371 GitHub stars~852 tokensUpdated yesterday
    Game DevelopmentAuto-check passed
  • HyperFrames Animation

    heygen-com/hyperframes

    Collects motion rules, scene blueprints, transitions and runtime adapters for HyperFrames video compositions, with GSAP as the default animation runtime.

    60k GitHub starsUsed in 3 repos~2.1k tokens
    Media & CreativeAuto-check passed
  • Phantom Motion

    pixelxzen/phantom-motion

    交互式动态视觉叙事生成器 v11.0 (Hybrid Drive Edition)。基于用户输入的任意主题关键词, 通过多轮交互式对话收集需求,利用 React 19 + Tailwind 4 驱动的 Minimal Mono 极简编辑器, 实时操纵隔离在 Iframe 中的硬核 GSAP/WebGL 影视级叙事引擎。

    185 GitHub stars~1k tokensUpdated 5 mo ago
    Frontend & DesignAuto-check passed
  • Inspira UI

    secondsky/claude-skills

    120+ Vue/Nuxt animated components with TailwindCSS v4, motion-v, GSAP, Three.js.

    227 GitHub stars~2.6k tokensUpdated 13 days ago
    Frontend & DesignAuto-check passed

More from EliasOulkadi/shokunin

All 49 skills in this repo
  • CI CD

    EliasOulkadi/shokunin

    Design CI/CD pipelines for GitHub Actions, GitLab CI, and CircleCI with matrix builds, test sharding, caching, Docker layer caching, OIDC auth, deployment strategies (rolling, blue-green, canary)…

    114 GitHub stars~3.4k tokensUpdated 6 days ago
    Auto-check: notes
  • Component Forge

    EliasOulkadi/shokunin

    Build production-grade components for React, Vue 3, and Svelte 5 with all states (loading, empty, error, success, idle), TypeScript strict, WCAG 2.2 accessibility, server components (RSC), and…

    114 GitHub stars~3.6k tokensUpdated 6 days ago
    Auto-check: notes
  • DB Admin

    EliasOulkadi/shokunin

    PostgreSQL database administration — backup/restore (pgdump, PITR, WAL archiving), health monitoring (connections, bloat, cache hit ratio, dead tuples), connection pooling (PgBouncer), replication…

    114 GitHub stars~2k tokensUpdated 6 days ago
    Auto-check: notes
  • DB Sculptor

    EliasOulkadi/shokunin

    Design database schemas with Prisma/Drizzle, PostgreSQL index strategy (B-tree, GIN, GiST, BRIN, Hash), query optimization (EXPLAIN ANALYZE), migration safety (expand/contract, zero-downtime), and…

    114 GitHub stars~3.1k tokensUpdated 6 days ago
    Auto-check: notes
  • Docker

    EliasOulkadi/shokunin

    Optimize Docker images with multi-stage builds, distroless bases, BuildKit cache mounts, multi-arch builds, compose watch, security hardening (non-root, seccomp, capabilities drop), and…

    114 GitHub stars~3.8k tokensUpdated 6 days ago
    Auto-check: notes
  • Error Handler

    EliasOulkadi/shokunin

    Design error handling, structured logging, and observability with OpenTelemetry (traces, metrics, logs), error classification, recovery patterns (retry with jitter, circuit breaker, bulkhead…

    114 GitHub stars~3.6k tokensUpdated 6 days ago
    Auto-check: notes

Works with

Questions about Motion Craft

What does Motion Craft do?

Design GPU-accelerated animations with Web Animations API (WAAPI), Scroll-Driven Animations (ScrollTimeline/ViewTimeline), FLIP technique, easing systems, and accessibility (prefers-reduced-motion). Motion Craft is an agent skill from EliasOulkadi/shokunin. Design GPU-accelerated animations with Web Animations API (WAAPI), Scroll-Driven Animations (ScrollTimeline/ViewTimeline), FLIP technique, easing systems, and accessibility (prefers-reduced-motion).

When should I use Motion Craft?

Motion Craft fits situations like: user asks to create animations; page transitions; interactive motion for web UIs; canvas-based animations (Three.js.

How do I install Motion Craft in Claude Code?

Run `npx skills add EliasOulkadi/shokunin --skill motion-craft -a claude-code`. Or copy the skill folder (.pack/skills/motion-craft in EliasOulkadi/shokunin) into .claude/skills/motion-craft in your project. Claude Code loads it when a task matches its description.

How do I install Motion Craft in Codex?

Run `npx skills add EliasOulkadi/shokunin --skill motion-craft -a codex`. Or copy the skill folder (.pack/skills/motion-craft in EliasOulkadi/shokunin) into .agents/skills/motion-craft in your project. Codex loads it when a task matches its description.

Can I use Motion Craft in Cursor, Gemini CLI or GitHub Copilot?

Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add EliasOulkadi/shokunin --skill motion-craft -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/motion-craft, .gemini/skills/motion-craft, .github/skills/motion-craft and .opencode/skills/motion-craft in your project.

What does Motion Craft need to run?

Going by SKILL.md and its folder, Motion Craft needs a shell for the scripts in its folder. Our summary lists: A Bash shell. Compatibility (from SKILL.md): opencode.

Does Motion Craft access the network?

SKILL.md names 2 domains. As links in the text: easing.dev and easings.co. This is read from the text; nothing was executed.

Is Motion Craft safe to install?

Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. The check reads SKILL.md only: the scripts in the folder are not scanned, so read them before running anything.

What licence does Motion Craft use?

Motion Craft is published under the MIT licence (declared in SKILL.md). It allows redistribution, so the full SKILL.md is shown on this page.

How many tokens does Motion Craft use?

About 6.4k tokens (SKILL.md is roughly 26k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full. Its references folder adds about 3k tokens, read only when the agent opens those files.

What are the alternatives to Motion Craft?

Skills that share tags, products or a category with Motion Craft: Guizang Product Video Skill (op7418/guizang-product-video-skill, 753 stars), Oma Design (first-fluke/oh-my-agent, 1.3k stars), Motion Design (WrongStack/WrongStack, 371 stars) and HyperFrames Animation (heygen-com/hyperframes, 60k stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.

Who maintains Motion Craft?

EliasOulkadi (a GitHub user) maintains it in EliasOulkadi/shokunin, which has 114 GitHub stars. The repository holds 49 skills in this directory. The repository was last updated on October 5, 2026.

Source: EliasOulkadi/shokunin on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.