Key insights
- Swap hardcoded hex for semantic tokens like
var(--brand)orvar(--error). Intent survives every redesign, and a single rename updates the whole app. - Build a numbered color scale (100–900) so every shade is systematic instead of a lucky guess, then map it to semantic names such as brand, success, and error.
- Define a type scale with fixed sizes and weights. Same size and weight everywhere means no hierarchy; a real scale separates heading from body at a glance.
- Base spacing on a 4px scale — space-1=4 up to space-16=64. Random gaps like 7px, 23px, or 11px read as sloppy, while scale-based gaps feel deliberate.
- Standardize components as variants, sizes, and states: primary/secondary/ghost/destructive buttons, small/medium/large sizing, and default/focus/error/disabled inputs.
- Match motion to intent — ease-out to enter, ease-in-out to move, ease-in to exit — and keep a duration scale from 100ms micro-interactions to 500ms complex transitions.
Do / Don't
- Do: Store every value as a named token so color, type, and spacing stay consistent across the app
- Do: Build numbered scales (color 100–900, spacing 4→64) so choices are systematic, not improvised
- Do: Tie easing and duration to the interaction's intent — entering, moving, or leaving
- Don't: Hardcode raw hex or pixel values inline
- Don't: Pick spacing by eye, 7px here and 23px there
- Don't: Give every text the same size and weight, killing all hierarchy