Same pixels, different product
Below are two buttons. Same typeface, same radius, same colors, same size. Screenshot them and diff the pixels: identical. Now use them.
The one on the right responds. It eases into its hover state instead of snapping there. It compresses under your click like something physical, and springs back when you let go. Nothing about the left one could be filed as a bug. It's just not finished.
transition: background-color 150ms ease-out,
transform 150ms ease-out;
button:active { transform: scale(0.97); }
button:focus-visible { outline: 2px solid; outline-offset: 2px; }What a micro-interaction actually is
A micro-interaction is the interface answering your body. You reach for a button: it acknowledges you. You press: it yields. You release: it comes back. You wait: it tells you it's working. None of this is decoration. It's feedback: the difference between pressing a button and clicking a picture of one.
The whole thing costs a few lines. An ease on hover, a scale to 0.97 on press, a spring on release. Said like that, the work sounds like typing those lines. The work is knowing the numbers.
It dies three times before production
If this layer is that cheap and that important, why does most of the web click like a picture? Because between intent and production, it gets three chances to die.
- In Figma. A frame can't hold 200 milliseconds. Prototype links simulate navigation, not resistance. The tool that owns design decisions literally cannot represent this one.
- In the handoff. I've written about the week I spent on a transition that arrived flat on the other side. Redlines carry positions and colors. They have no unit for what a press should feel like.
- In the prompt. Feel can't be described, only recognized. Ask for “a satisfying press” and the model has to guess which of ten thousand satisfying presses you mean. It picks the median one. The median is exactly what your product shouldn't feel like.
The loading dilemma
Here is where judgment stops being abstract. Press deploy below. The label becomes a spinner, and the button has to decide what happens to its width.
A is the default, and what most generated output ships. B is the safe fix. C is the finished one: the width moves on the same curve as everything else, so the button stays one object instead of becoming two states. No spec chooses between B and C. Your finger does.
.label { width: var(--label-width); overflow: hidden;
transition: width 300ms cubic-bezier(0.22, 1, 0.36, 1); }
.loading .label { width: 20px; }Why AI, specifically, can't finish it
This is the 70/30 rule at component scale. The model generates the entire button in seconds, so the 70 is free now. But finishing is a judgment about this product, this brand, this user mid-task, and that judgment isn't written anywhere the model can read. It optimizes toward the median of everything that has ever been praised. Your product's feel is, by definition, a deviation from that median.
So AI didn't make micro-interactions less valuable. It made them the differentiator. When every product ships correct, feel is what's left.
The designer who pushes
A micro-interaction can't be handed off. It has to be made in the medium: tuned at 60fps, felt, adjusted, felt again. Which means the person who owns the intent has to be in the code, or the intent dies in translation.
That's not a designer doing an engineer's job. It's the only place this particular design decision can be made. The 200 milliseconds were always design. AI just made everything around them cheap enough that finishing is now the job.