Notes from production
UI/UXMotionDesign Systems

Polish your UI with the Emil design-engineering skill

This site sells engineering discipline, so it has to be disciplined — clean console, fast SSG, two-hex restraint. We ran Emil Kowalski's design-engineering skill over the interface and it found the one thing our motion system was missing: press feedback. Here's what we changed, the before/after, and why we drew the comparison in SVG instead of a Remotion-rendered GIF.

What a "design skill" actually is

Emil Kowalski builds the components a lot of the web quietly runs on — Sonner (toasts) and Vaul (drawers) — and teaches the craft at animations.dev. His skill is that taste, written down as rules an AI agent can apply: a portable file that encodes how interfaces should feel — when to animate and when not to, which easing, how fast, and the invisible details that separate "works" from "feels right."

You point your coding agent at the skill and ask for a polish pass. It reviews your real CSS against the rules and proposes concrete Before → After fixes — not vibes, a diff. It's the same move we make with AI everywhere on this site: encode the expert's judgment, then let it run.

The gap it found: nothing answered the press

Our buttons and cards already lifted on hover. But there was no :active state anywhere — so the moment a user actually pressed, nothing happened. The interface reacted to the cursor passing over it, but not to the click itself. That's the single most-felt micro-interaction on any site, and it was silent.

BEFOREAFTERPressrigid on pressPressscale 0.96 · ~90ms
Before: the button only knew about the cursor. After: it answers the press — a fast dip to 0.96 that settles flat, with a snappy release. The whole point of a pressable is that it feels pressed.

The before → after, mapped

One CSS-only pass, transform/opacity only (so it stays on the GPU), tokens unchanged:

ElementBeforeAfterWhy
Buttonshover lift only:active { transform: scale(0.96) }, settles to the resting shadowEvery CTA now answers the press — fast down, snappy release
Clickable cardshover lift only:active { transform: scale(0.99) }Cards feel “pushed” on tap; subtle because they’re large
Carousel arrowscolour change onlyadded transform to the transition + :active { scale(0.9) }Round buttons felt inert on click
FAQ accordionanswer hard-snaps openanswer fades + rises in over 0.18sElements appearing with no transition feel broken

The release matters as much as the press. The dip is fast (~90ms) but the rebound rides the base 0.2sdeliberate down, snappy up. Pressables should feel decisive going in and effortless coming back.

The rules behind the fixes

The skill isn't a style; it's a short list of physics-aware defaults. The ones that drove this pass:

Here's the actual press, specificity and all — the :active rule has to win over the hover lift, and the press is faster than the release:

/* fast down (~90ms), snappy release via the base 0.2s — and the press
   wins over the hover lift by source order + specificity. */
.rv-btn:active:not(:disabled) {
  transform: scale(0.96);
  transition-duration: 0.09s;
}

And because motion is never mandatory, the FAQ reveal opts out cleanly:

Gate motion on the user's preference

  • Every new animation has a @media (prefers-reduced-motion: reduce) path. The FAQ answer's fade-and-rise simply turns off; the panel still opens, just without the movement.

Don't ship motion that can't be switched off

  • An entrance with no reduced-motion fallback is an accessibility bug, not a flourish. "Fewer and gentler," never "all or nothing."

SVG or Remotion for the before/after?

The comparison above is inline SVG, not a recorded GIF. That was a deliberate call — Remotion (React → video) is excellent, but it's the wrong tool for an embedded figure on a site like this:

  • Theme-aware: the figure recolours for light/dark from the same --rv-* tokens. A baked GIF is frozen in one theme.
  • Weightless + crawlable: a few hundred bytes of markup, readable by search and answer engines; no raster asset to ship or cache.
  • On-system: every diagram here is already inline SVG + CSS, CSP-clean, reduced-motion-aware.

  • A standalone clip for social (LinkedIn, X) or a landing-page hero, where you want a polished rendered video and theme/seo don't apply.
  • Frame-exact, heavy motion that CSS can't express — particles, easing you want to scrub, audio-synced sequences.
  • It runs outside the static build, producing a raster file — great for distribution, wrong for an in-article diagram.

Rule of thumb: SVG for figures that live inside the page; Remotion for a video that leaves it. If we cut a shareable before/after clip later, that's exactly when Remotion earns its place.

Run it on your own UI

The pass is repeatable and low-risk:

  1. Point your agent at the skill and ask for a polish pass on a component or page.
  2. Read the Before → After table it returns — each row is a specific rule, not a guess.
  3. Apply the wins as CSS-only changes (transform/opacity), each :active verified to beat its :hover by specificity.
  4. Validate: rules parse into the cascade, zero console errors, reduced-motion honored, build clean. Ship the diff.

None of this is visible in a screenshot — it lives entirely in the press. That's the point: a thousand barely-audible details, all in tune.

Common questions

What is the Emil design-engineering skill?

It's Emil Kowalski's UI-craft philosophy written as rules an AI coding agent can apply — when to animate, which easing and duration, press feedback, springs, and accessibility. You point your agent at it and ask for a polish pass; it reviews your real code and returns concrete Before → After fixes. Emil is the author of Sonner and Vaul and teaches the craft at animations.dev.

What is press feedback and why does it matter?

Press feedback is the small, fast response a pressable element gives the moment you click or tap it — typically scaling down to about 96–98%. It confirms the interface heard you. Hover states react to the cursor passing over; press feedback reacts to the action itself, which is the interaction users feel most. Adding it was the single biggest improvement in this pass.

Should I use SVG or Remotion to show a before/after?

For a figure embedded inside a page, use inline SVG: it's theme-aware, weightless, crawlable, and CSP-clean. Use Remotion (React → video) when you need a standalone clip to share off-site — social posts, a landing-page hero — or frame-exact motion CSS can't express. SVG for figures that live in the page; Remotion for a video that leaves it.

Sources

  1. Emil Kowalski — the design-engineering skill
  2. animations.dev — Emil Kowalski's animation course
  3. Remotion — make videos programmatically in React
  4. MDN — prefers-reduced-motion