
The temptation is to jump straight into building a Button component. But the most impactful work in a design system happens at the token layer: colors, spacing, typography scales, and radii. Get these right and every component you build later inherits consistency for free.
We started by auditing every color, font size, and spacing value across three products. The result was a token file with about 60 values that covered 95% of our UI. The remaining 5% were one-off values that shouldn't have existed in the first place.
:root {
--space-1: 4px;
--space-2: 8px;
--space-3: 12px;
--space-4: 16px;
--space-6: 24px;
--space-8: 32px;
--radius-sm: 4px;
--radius-md: 8px;
--radius-lg: 12px;
}Early on we made every component accept a dozen props for every visual variation. A button had size, variant, color, iconPosition, isLoading, isFullWidth, and more. The API surface became unmanageable, and testing alone required hundreds of combinations.
We shifted to a composition model. Instead of one monolithic Button, we built small primitives (ButtonRoot, ButtonIcon, ButtonSpinner) that could be assembled. This made each piece simple to test and gave consumers the flexibility to create combinations we hadn't anticipated.