How a component gets made.
Five decisions, in the order we make them. Each one narrows the next, which is why so few of them feel like decisions by the end.
01
Start from one token
Every surface steps up from the page colour. The card is one step above the background, the popover one step above the card, and the hover fill one step above that. A card stops being a colour you chose and becomes a fact about the page.
Hairlines are translucent, so they sit on any of those surfaces without a second value. Two overlapping hairlines add up to something heavier, which is why a grid of tiles shares its lines inside one frame instead of giving each tile a border of its own.
The test is a theme change. Swap the tokens and nothing in the component should need a second look. If a value survives the swap and looks wrong, it was never a token, and it goes back in the list to fix.
02
Round from the outside in
A nested corner shares its centre with the corner around it, so the inner radius is the outer radius minus the gap. A 12px card with a 4px gap holds 8px tiles. Get that one subtraction wrong and the gap pinches at the corners, even if nobody can say why it feels off.
Controls follow the same rule from the other direction. Anything meant to read as a pill takes a full radius at every size, so a 28px button and a 44px one are clearly the same shape and not two near misses.
Radius is also a ratio. A tile sits around a quarter of its side, a card closer to a twentieth. Large things with tile radii look inflated, and small things with card radii look sharp and cheap.
03
Set the type before the layout
Prose wants 45 to 75 characters on a line, which is the real reason the column is the width it is. The grid comes second. Start from the measure and the page mostly lays itself out around it.
Hierarchy comes from size and tone, not weight. A headline is large and bright, a paragraph is smaller and grey, and mono is kept for things that are read as data: counts, dates, shortcuts and ids.
Figures that change sit in tabular numerals, so a counter ticking from 9 to 10 does not push everything next to it. It is one property, and readers feel it on every dashboard they use.
04
Move only what explains
Motion needs a reason a person could say out loud. It shows where something came from, or confirms that a press landed, or bridges a change that would otherwise jump. Looking nice is a reason on a landing page once and nowhere else.
Transform and opacity do almost all of the work, because the browser can run them without measuring anything again. A frame at 60 hertz gives you 16.7 milliseconds, and half that at 120. A layout pass on a busy page can spend several frames on its own.
Reduced motion is the first state to design, not the last. If the page reads with nothing moving, the motion is an accent. If it does not, the motion was holding up the content and needs to come out.
05
Let the gate have the last word
A component is done when a script says so. It runs in both themes at two widths, axe checks every state, and two screenshots a second apart must match under reduced motion. Taste decides what to build, and the gate decides whether it shipped.
What is left is a person looking at a contact sheet and choosing keep, redo or drop. Most of the library went through that sheet more than once.