Motion/animation design skill with 3-designer lens (Emil Kowalski, Jakub Krehel, Jhey Tompkins). Two modes: Create and Audit. Complements frontend-design (broad) with deep motion expertise. Integration points: - skills-external/design-motion-principles/ — skill files + references - link.sh EXTERNAL_SKILLS — symlink to ~/.claude/skills/ - install-plugins.sh step 8c — presence check - update-all.sh step 7.2 — sync from GitHub - profiles: design, full, web, web-full — listed as external - plugin-advisor — decision table, recommended sets, conditional rules - design-gate — symlink check + non-blocking warning if missing Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
12 KiB
Workflow: Audit Mode
Review existing motion design and produce a per-designer report. Reconnaissance first, then a full audit, then a structured report. Never apply rules blindly.
Required Reading
Read as you reach each step (not all upfront):
references/audit-checklist.md— your systematic guide (STEP 2)- The weighted designer file(s) —
emil-kowalski.md,jakub-krehel.md,jhey-tompkins.md(STEP 2) references/accessibility.md— mandatory every audit (STEP 2)references/anti-checklist.md— the quality gate: AI-slop motion categories + anti-patterns to flag (STEP 2)references/output-format.md— the report template, HTML mode + terminal mode (STEP 3)references/demo-shell.html— the demo-card template for HTML-mode per-finding demos (STEP 3)
STEP 1: Context Reconnaissance (DO THIS FIRST)
Before auditing any code, understand the project context.
Gather Context
Check these sources:
- CLAUDE.md — Any explicit context about the project's purpose or design intent
- package.json — What type of app? (Next.js marketing site vs Electron productivity app vs mobile PWA)
- Existing animations — Grep for
motion,animate,transition,@keyframes. What durations are used? What patterns exist? - Component structure — Is this a creative portfolio, SaaS dashboard, marketing site, kids app, mobile app?
Motion Gap Analysis (CRITICAL - Don't Skip)
After finding existing animations, actively search for missing animations. These are UI changes that happen without any transition:
Search for conditional renders without AnimatePresence:
# Find conditional renders: {condition && <Component />}
grep -n "&&\s*(" --include="*.tsx" --include="*.jsx" -r .
# Find ternary UI swaps: {condition ? <A /> : <B />}
grep -n "?\s*<" --include="*.tsx" --include="*.jsx" -r .
For each conditional render found, check:
- Is it wrapped in
<AnimatePresence>? - Does the component inside have enter/exit animations?
- If NO to both → this is a motion gap that needs fixing
Common motion gap patterns:
{isOpen && <Modal />}— Modal appears/disappears instantly{mode === "a" && <ControlsA />}— Controls swap without transition{isLoading ? <Spinner /> : <Content />}— Loading state snapsstyle={{ height: isExpanded ? 200 : 0 }}— Height changes without CSS transition- Inline styles with dynamic values but no
transitionproperty
Where to look for motion gaps:
- Inspector/settings panels with mode switches
- Conditional form fields
- Tab content areas
- Expandable/collapsible sections
- Toast/notification systems
- Loading states
- Error states
State Your Inference
After gathering context, tell the user what you found and propose a weighting:
## Reconnaissance Complete
**Project type**: [What you inferred — e.g., "Kids educational app, mobile-first PWA"]
**Existing animation style**: [What you observed — e.g., "Spring animations (500-600ms), framer-motion, active:scale patterns"]
**Likely intent**: [Your inference — e.g., "Delight and engagement for young children"]
**Motion gaps found**: [Number] conditional renders without AnimatePresence
- [List the files/areas with gaps, e.g., "Settings panel mode switches", "Loading states"]
**Proposed perspective weighting**:
- **Primary**: [Designer] — [Why]
- **Secondary**: [Designer] — [Why]
- **Selective**: [Designer] — [When applicable]
Does this approach sound right? Should I adjust the weighting before proceeding with the full audit?
Use the Context-to-Perspective Mapping table in SKILL.md to propose the weighting.
Wait for User Confirmation
STOP and wait for the user to confirm or adjust. Do not proceed to the full audit until they respond.
If AskUserQuestion is available, present the decision as tappable options:
- Confirm weighting — Proceed with the proposed primary/secondary/selective designers
- Adjust primary — Swap which designer is primary (e.g., prioritize delight over restraint)
- Adjust secondary — Change the secondary lens while keeping primary
- Rebuild weighting — The project type inference was wrong; start over
Otherwise ask in plain text: "Does this weighting sound right, or should I adjust?"
If they adjust (e.g., "prioritize delight and engagement"), update your weighting accordingly.
STEP 2: Full Audit (After User Confirms)
Once the user confirms, perform the complete audit by reading the reference files in this order:
2a. Read the Audit Checklist First
Read references/audit-checklist.md — Use this as your systematic guide. It provides the structured checklist of what to evaluate.
2b. Read Designer Files for Your Weighted Perspectives
Based on your context weighting, read the relevant designer files:
- Read
references/emil-kowalski.mdif Emil is primary/secondary — Restraint philosophy, frequency rules, decision frameworks - Read
references/jakub-krehel.mdif Jakub is primary/secondary — Production polish philosophy, what to check - Read
references/jhey-tompkins.mdif Jhey is primary/secondary — Playful experimentation philosophy, opportunities to surface
2c. Read Topical References as Needed
- Read
references/accessibility.md— MANDATORY. Always check for prefers-reduced-motion. No exceptions. - Read
references/anti-checklist.md— Apply this as the audit's quality gate. AI-slop categories at the top (pulsing indicators, hover-scale-on-everything, stagger-spam, etc.) trigger findings; perspective-specific and general anti-patterns sit below. Each category includes a frequency heuristic so single intentional uses don't trip the gate. - Read
references/performance.md— If you see complex animations, check for GPU optimization issues - Read
references/motion-cookbook.md— Reference when making specific implementation recommendations (the recommended fix code, including the per-finding demo motion in HTML mode)
STEP 3: Output Format (HTML by default)
The audit produces a self-contained HTML report with auto-looping CSS demos beside Critical and Important findings. Read references/output-format.md for the full template (both HTML mode and terminal mode).
Default behavior — write and open the HTML report
-
Resolve the write location. The file is written to
motion-audits/{project-name}-{ISO-date}.htmlin the audited project's root.- Audited project root: run
git rev-parse --show-toplevelfrom the agent's cwd. If it succeeds, use that path. If it fails (no.gitancestor), use cwd. {project-name}: thenamefield frompackage.jsonat the project root if it exists; else thenamefield frompyproject.toml; else the basename of the project root. Strip any scoping prefix (@scope/pkg→pkg) and sanitize to lowercase kebab-case ([a-z0-9-], replace others with-).{ISO-date}: today's date asYYYY-MM-DD.- Example:
<project-root>/motion-audits/my-app-2026-05-20.html. - Do not modify
.gitignore. The user seesmotion-audits/ingit statusand decides whether to ignore it.
- Audited project root: run
-
Read
references/demo-shell.htmland use it as the template for each demo card. Embed one card per Critical + Important finding (Opportunities do not get demo cards). Use the suffixed-naming contract —@keyframes motion-{n}-...and.demo-card-{n}__motion-target,{n}= the finding's 1-indexed position across the whole report — so multiple findings don't collide on CSS names. -
Generate per-finding motion code by reading the audited code, the relevant lens reference, and
references/motion-cookbook.mdfor the recipe. Use the shell's 0% / 66% / 100% cadence atanimation-duration: 3s(~2s motion, ~1s hold, loop). The@keyframes100% state must match the motion-target's default static rendering so the shell'sprefers-reduced-motionguard shows the correct final visual. -
Write the file. Create
motion-audits/if it doesn't exist. Write the complete self-contained HTML document. -
Open in the default browser via OS-detected Bash dispatch:
path="<absolute path to the HTML file>" if [ -n "$WSL_DISTRO_NAME" ] || grep -qi microsoft /proc/version 2>/dev/null; then win_path=$(wslpath -w "$path") cmd.exe /c start "" "$win_path" 2>/dev/null else case "$(uname -s)" in Darwin) open "$path" ;; Linux) xdg-open "$path" ;; MINGW*|MSYS*|CYGWIN*) start "" "$path" ;; *) echo "Unknown platform — open this file manually: $path" ;; esac fiIf the open command returns non-zero or the platform is unrecognized, print
Open this file in your browser: {absolute path}and continue. Never abort the audit because of a failed browser-open. -
Print the 3-line terminal summary:
🎬 Motion audit complete — 🔴 {N} Critical · 🟡 {N} Important · 🟢 {N} Opportunities 📄 Report: {absolute path} 💡 Want the full report inline instead? Re-run with --terminal or say "show inline".
Terminal mode (flag-triggered)
When the user signals terminal mode (--terminal / --inline / --no-html flag, or "show the full report inline" / "skip the HTML" / "terminal only"), skip the HTML write and the browser-open and render the decorated-markdown report inline per references/output-format.md terminal mode. Do not print the 3-line summary in this case.
Do not summarize the audit content in either mode — users want full per-lens perspectives.
Agent Gotchas (Self-Check Before Writing the Report)
Common failure modes during HTML report generation. Most break silently or only manifest when a second finding lands in the same report.
- Don't reuse keyframe or class names across findings. Each demo uses
@keyframes motion-{n}-...and.demo-card-{n}__motion-targetwhere{n}is the 1-indexed position across the WHOLE report. Duplicate names mean the second finding shadows the first and the first demo breaks silently. - Don't redefine the shell's CSS variables. Per-finding code uses
var(--bg),var(--fg),var(--border),var(--accent),var(--loop-dim),var(--sans),var(--mono). Hard-coding colors or fonts breaks dark mode and typography consistency. - Don't write per-finding overrides inside the
prefers-reduced-motionblock. The shell's guard collapses all[class*="__motion-target"]animations. Make the@keyframes100% state match the motion-target's default static rendering instead. - Don't include demo cards for Opportunities. Demos are reserved for Critical and Important. Surface Opportunities in text only.
- Don't animate the report itself. No entrance, scroll, or mount animations on the report chrome — only the demo cards animate. Animating the report reproduces the AI-slop patterns the audit exists to catch.
- Don't write to cwd if
git rev-parse --show-toplevelsucceeds. The report goes to{project-root}/motion-audits/. Only fall back to cwd when git returns nonzero. - Don't abort the audit if browser-open fails. A non-zero exit code is a "no default handler" condition, not an error. Print the path and continue.
- Don't modify
.gitignore. The skill never touches it. The user addsmotion-audits/themselves if they want. - Don't summarize per-lens findings. Each section needs its own findings + working-well items + the
Through {Designer}'s lens:summary.
Success Criteria
- Context gathered (CLAUDE.md, package.json, existing animations, structure)
- Motion gap analysis run — conditional renders checked for missing animation
- Weighting proposed and confirmed by the user
- Audit checklist worked through systematically
- Anti-checklist applied — AI-slop categories checked against the codebase
- Accessibility checked — prefers-reduced-motion verified (mandatory)
- HTML report written to
motion-audits/, opened in browser, 3-line summary printed (or terminal-mode report rendered inline when flagged) - Report follows output-format.md with full per-lens sections; Critical + Important findings have looping demo cards