name: toge:animations description: Animation and micro-interaction principles from Emil Kowalski and Jakub Krehel. Use when adding animations, hover states, enter/exit transitions, icon state changes, button feedback, or any motion detail to a prototype. Triggers on "add animations", "make it feel better", "feels off", "hover state", "transition", "easing", "scale on press", "micro-interactions".
UI Polish — Design Engineering Principles
Synthesized from Emil Kowalski (animations.dev) and Jakub Krehel (make-interfaces-feel-better). Great interfaces rarely come from one thing. It's the compound of invisible details.
Philosophy
Most details users never consciously notice. That is the point. When a feature functions exactly as someone assumes it should, they proceed without a second thought. Beauty is underutilized in software — good defaults and good animations are real differentiators.
Good taste is a trained instinct. Develop it by studying great work, reverse-engineering animations, and asking why something feels right.
Quick Reference
| Category | When to Use |
|---|---|
| Animations | Animation decisions, easing, duration, enter/exit, icon animations, scale on press, springs |
| Performance | GPU-compositable properties, transition specificity, will-change usage |
Typography and surfaces are applied during the Prototype phase — see
archive/prototype/SKILL.mdPrototype Conventions (the prototype skill is temporarily archived).
Common Mistakes
| Issue | Fix |
|---|---|
| Same border radius on parent and child | outerRadius = innerRadius + padding |
| Icons look off-center | Align optically, not geometrically |
| Hard borders between sections | Layered box-shadow with transparency |
transition: all |
Specify exact properties |
scale(0) entry |
Start from scale(0.95) + opacity: 0 |
ease-in on UI element |
Switch to ease-out or custom curve |
| Duration > 300ms on UI | Reduce to 150–250ms |
| Same enter/exit speed | Make exit faster |
| Elements all appear at once | Stagger ~100ms between groups |
| Animation on keyboard action | Remove entirely |
| Hover without media query | Add @media (hover: hover) and (pointer: fine) |
| Numbers cause layout shift | font-variant-numeric: tabular-nums |
| Heavy text on macOS | -webkit-font-smoothing: antialiased |
| Heading wraps awkwardly | text-wrap: balance |
| Tiny hit area on small control | Pseudo-element to 40×40px |
| Images look flat | outline: 1px solid rgba(0,0,0,0.06) |
Framer Motion x/y under load |
Use transform: "translateX()" |
transform-origin: center on popover |
Set to trigger origin (modals exempt) |
| Animation on page load | initial={false} on AnimatePresence |