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>
5.9 KiB
Emil Kowalski's Animation Principles
Emil Kowalski is a Design Engineer at Linear (previously Vercel). Creator of Sonner, Vaul, and the "Animations on the Web" course. His approach emphasizes restraint, speed, and purposeful motion.
This file is Emil's philosophy and decision frameworks — the judgment for whether and when to animate. Implementation code lives in motion-cookbook.md (cross-referenced below).
Core Philosophy: Restraint & Purpose
Emil's defining contribution to motion design thinking is knowing when NOT to animate.
"The goal is not to animate for animation's sake, it's to build great user interfaces."
His key question for any interaction: "Should this animate at all?"
The Frequency Rule
Animation appropriateness depends on interaction frequency:
| Frequency | Recommendation |
|---|---|
| Rare (monthly) | Delightful, morphing animations welcome |
| Occasional (daily) | Subtle, fast animations |
| Frequent (100s/day) | No animation or instant transitions |
| Keyboard-initiated | Never animate |
The Raycast example: A tool used constantly throughout the day benefits from zero animation. Users with clear goals "don't expect to be delighted" and prioritize frictionless workflow.
Speed is Non-Negotiable
"UI animations should generally stay under 300ms."
A 180ms animation feels more responsive than 400ms. Speed creates perceived performance. When in doubt, go faster.
The 7 Practical Animation Tips
Emil's decision checklist. Code for each is in the cookbook section noted.
- Scale your buttons — Subtle
scale(0.97)on:activefor immediate tactile feedback. → cookbook §10 - Don't animate from
scale(0)— It creates unnatural motion. Start fromscale(0.9)or higher. → cookbook §10 - Tooltip delay patterns — First tooltip in a group: delay + animation. Subsequent: instant. → cookbook §10
- Custom easing is essential — "Easing is the most important part of any animation. It can make a bad animation feel great." Built-in
ease/ease-in-outlack strength; use custom Bézier curves (easing.dev, easings.co). → cookbook §2 - Origin-aware animations — Motion should originate from its logical source; a dropdown expands from its trigger, not from center. → cookbook §13
- Keep animations fast — Under 300ms for UI; remove animation entirely for high-frequency interactions.
- Use blur when nothing else works —
filter: blur(2px)masks imperfections during rough state transitions. → cookbook §10
Signature Techniques (decision context — code in cookbook)
| Technique | When Emil reaches for it | Cookbook |
|---|---|---|
| Clip-path animations | Reveals and tab transitions — hardware-accelerated, no layout shift, no extra DOM | §9 |
| Spring physics | Any value that should interpolate smoothly rather than snap (e.g. mouse position) | §12 |
| CSS transitions over keyframes | Anything the user can rapidly re-trigger — keyframes can't retarget mid-flight | §11 |
| Direct style updates | Frequent updates like drag — CSS variables cause cascade recalculation | §11 |
| Momentum-based dismissal | Swipe-to-dismiss — use velocity, not distance thresholds | §11 |
Interruptibility
Great animations can be interrupted mid-play and respond naturally. Framer Motion supports this natively; CSS transitions allow smooth interruption before completion. Test by clicking rapidly — animations should blend, not queue.
When to Use Each Approach
| Context | Approach |
|---|---|
| Keyboard shortcuts | No animation |
| High-frequency tool | Minimal or no animation |
| Daily-use feature | Fast, subtle animation (180-250ms) |
| Onboarding/first-time | Delightful animations welcome |
| Marketing/landing page | Full creative expression |
| Banking/serious UI | Minimal, functional motion |
| Playful brand | Bouncy, elastic easing appropriate |
Invisible Quality: Lessons from Sonner & Vaul
Emil's open-source libraries (Sonner for toasts, Vaul for drawers) reveal his philosophy in shipped code. The throughline: every detail serves invisible quality — users shouldn't notice polished interactions, they should just feel right.
"When a feature functions as you assume it should, you proceed without giving it a second thought, which is our goal."
Details that matter: matching native motion curves for familiarity (Vaul uses iOS's cubic-bezier(0.32, 0.72, 0, 1)), damping near boundaries ("things in real life don't suddenly stop, they slow down first"), multi-touch protection, pointer capture during drags, pausing timers when the tab is inactive.
Sonner Defaults
| Setting | Value | Rationale |
|---|---|---|
| Duration | 4000ms | Long enough to read, short enough to not annoy |
| Animation | 400ms ease | Smooth but snappy |
| Position | bottom-right | Convention, out of primary content |
| Dismissible | true | User control by default |
Vaul Defaults
| Setting | Value | Rationale |
|---|---|---|
| Duration | 500ms | Match iOS sheet feel |
| Easing | cubic-bezier(0.32, 0.72, 0, 1) | iOS-native curve |
| Modal | true | Focus management, overlay |
| Direction | bottom | Convention for mobile sheets |
Emil vs. Jakub vs. Jhey
| Aspect | Emil | Jakub | Jhey |
|---|---|---|---|
| Focus | Restraint & speed | Subtle polish | Playful experimentation |
| Key question | "Should this animate?" | "Is this subtle enough?" | "What could this become?" |
| Signature technique | Frequency-based decisions | Blur + opacity + translateY | CSS custom properties |
| Ideal context | High-frequency tools | Production polish | Learning & exploration |
Synthesis: Use Emil's framework to decide IF you should animate. Use Jakub's techniques for HOW to animate in production. Use Jhey's approach for learning and experimentation.