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>
122 lines
5.9 KiB
Markdown
122 lines
5.9 KiB
Markdown
# 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.
|
|
|
|
1. **Scale your buttons** — Subtle `scale(0.97)` on `:active` for immediate tactile feedback. → cookbook §10
|
|
2. **Don't animate from `scale(0)`** — It creates unnatural motion. Start from `scale(0.9)` or higher. → cookbook §10
|
|
3. **Tooltip delay patterns** — First tooltip in a group: delay + animation. Subsequent: instant. → cookbook §10
|
|
4. **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-out` lack strength; use custom Bézier curves (easing.dev, easings.co). → cookbook §2
|
|
5. **Origin-aware animations** — Motion should originate from its logical source; a dropdown expands from its trigger, not from center. → cookbook §13
|
|
6. **Keep animations fast** — Under 300ms for UI; remove animation entirely for high-frequency interactions.
|
|
7. **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.
|