skip to content

[EXAMPLES] /examples?view=systems

What I look at

Real sites, the design systems behind the best of them, breakdowns from the people who made them, and the way I read all of it.

Showing Design systems

A design system is the set of rules behind a look: the type sizes, colour tokens (named colours), spacing, motion and states. I read these for the rules, not the looks. Each card draws the system in plain HTML from its public docs. Where I couldn’t check a number, I describe it instead.

Systems I learn from

[01]

Vercel Geist

Vercel's design system. Geist Sans and Geist Mono, a grey-first palette, and colour scales where every step has one job.

specimen · Geist Sans, with Geist Mono for code and labels

  • heading-72 · 72
  • heading-48 · 48
  • heading-32 · 32
  • heading-20 · 20
  • copy-16 · 16
  • label-13 · 13
  1. Step 100: bg
  2. Step 200: bg hover
  3. Step 300: bg active
  4. Step 400: border
  5. Step 500: border hover
  6. Step 600: border active
  7. Step 700: solid
  8. Step 800: solid hover
  9. Step 900: text 2
  10. Step 1000: text 1
Structure, drawn in grey. Ten scales (gray, gray-alpha, blue, red, amber, green, teal, purple, pink) share these ten steps.

Geist names each style by its size: text-heading-72 down to text-heading-14, then label, copy and button styles.

5 things I steal

Type scale
Name styles by their size and role (heading-32, copy-16, label-13). Nobody has to guess what 'h3' means.
Colour tokens
Ten steps per colour, each with one job: 100 to 300 backgrounds, 400 to 600 borders, 700 to 800 solid fills, 900 to 1000 text.
Spacing
Keep space in a small set of steps and let grey borders, not boxes of colour, separate things.
Motion
Quiet, short transitions on hover and open. Motion confirms an action; it never performs.
States
Default, hover and active are neighbouring steps on the same scale, so every state is one step away.

Do this with the toolkit

I set my greys as ten role-named steps with the oklch picker, then wire them into shadcn's CSS variables.

read the source ↗ (Vercel Geist, opens in a new tab)

[02]

Linear

Linear's dark, dense app UI. Its 2024 redesign turned 98 hand-set theme variables into three inputs, generated in the LCH colour space.

specimen · Inter Display for headings, Inter for everything else

  • base colour
  • accent colour
  • contrast

I haven't checked Linear's exact sizes, so I don't draw them. What Linear documents is the pairing: Inter Display for headings, Inter for the dense UI.

5 things I steal

Type scale
Use two cuts of one family: a tighter display cut for headings and the plain one for dense UI.
Colour tokens
Generate a theme from three inputs (base, accent, contrast) instead of hand-picking every surface.
Spacing
Density is a feature. Tight rows, aligned edges and less chrome let more content fit without noise.
Motion
Fast and small. Panels and menus arrive quickly and never block the next keypress.
States
Elevation and hover come from opacities of black and white, so they work on any generated theme.

Do this with the toolkit

I pick base and accent with the oklch picker (LCH's close cousin), then set hover and elevation as white at low opacity.

read the source ↗ (Linear, opens in a new tab)

[03]

Stripe

Stripe's marketing site and its UI toolkit for apps. A strict column grid, calm type, and colour that only moves where it means something.

specimen · A clean grotesk for text; described, not measured

I have not verified Stripe's exact sizes, so I don't draw them. The lesson is the grid: every section sits on the same column lines.

5 things I steal

Type scale
Few sizes, used strictly. Headlines carry the energy, body text stays quiet and readable.
Colour tokens
A living gradient carries the brand, while the UI around it stays white, grey and one accent.
Spacing
A visible column grid (the Connect page even draws its stripes with CSS Grid) keeps dense pages calm.
Motion
Only transform and opacity, mostly under 500ms, started when it scrolls into view.
States
Pick the lightest tool that works: CSS first, the Web Animations API next, a library last.

Do this with the toolkit

I build the gradient with ShaderGradient or Paper Shaders and keep the rest of the page on GSAP with transform and opacity only.

read the source ↗ (Stripe, opens in a new tab)

[04]

Apple HIG

Apple's Human Interface Guidelines. Rules for every Apple platform, built on San Francisco and Dynamic Type, where text sizes follow the reader's settings.

specimen · San Francisco (SF Pro), sized by Dynamic Type

  • Large Title · 34
  • Title 1 · 28
  • Title 2 · 22
  • Title 3 · 20
  • Body · 17
  • Subheadline · 15
  • Footnote · 13
  • Caption 2 · 11

iOS text styles at the default Large setting, in points. Headline is also 17, set semibold.

5 things I steal

Type scale
Name styles by purpose (Title, Body, Footnote), not by size, so they can all grow together.
Colour tokens
System colours adapt to light, dark and high contrast. Ask for 'label' or 'secondary label', not a hex.
Spacing
Hit targets at least 44 by 44 points, even when the icon is smaller.
Motion
Motion should explain where things came from, and it respects the Reduce Motion setting.
States
Every control has clear pressed, disabled and focused looks that don't rely on colour alone.

Do this with the toolkit

I set type in rem so it follows the reader's settings, and run the Web Interface Guidelines skill to check hit sizes and reduced motion.

read the source ↗ (Apple HIG, opens in a new tab)

[05]

Material 3

Google's design system. Fifteen named text styles, colour roles made from one source colour, and state layers for every interaction.

specimen · Roboto by default; any family can fill the roles

  • Display L · 57
  • Display S · 36
  • Headline L · 32
  • Title L · 22
  • Body L · 16
  • Label L · 14
  • Label S · 11
  • primary
  • on-primary
  • primary-container
  • on-primary-container
  • surface
  • on-surface
  • outline
  • error

Seven of the fifteen styles (display, headline, title, body, label, each large, medium and small), from the material-web tokens.

5 things I steal

Type scale
Five roles times three sizes. Fifteen styles is enough for any app, and each has a clear job.
Colour tokens
Roles come in pairs: every 'primary' has an 'on-primary' for the text on top, so contrast is designed in.
Spacing
A 4dp grid with shape tokens for corner radius, from none to full.
Motion
Easing and duration are tokens too, so every transition in the app feels related.
States
A state layer: the content colour laid over the surface at 8% on hover, 12% on focus and press, 16% on drag.

Do this with the toolkit

I copy the state-layer idea into Tailwind: one hover overlay at 8%, one pressed at 12%, and ease tokens picked on easings.net.

read the source ↗ (Material 3, opens in a new tab)

[06]

Radix + shadcn

Radix gives accessible primitives and 12-step colour scales. shadcn/ui gives you the component code itself, styled with a short list of CSS variables.

specimen · Whatever you choose; shadcn doesn't set a type scale

  1. Step 1: app bg
  2. Step 2: subtle bg
  3. Step 3: ui bg
  4. Step 4: ui hover
  5. Step 5: ui active
  6. Step 6: border
  7. Step 7: border ui
  8. Step 8: border hover
  9. Step 9: solid
  10. Step 10: solid hover
  11. Step 11: low text
  12. Step 12: high text
Radix Colors: twelve steps per scale, each step with a job. Drawn in grey.
  • --background
  • --foreground
  • --primary
  • --primary-foreground
  • --muted
  • --accent
  • --destructive
  • --border
  • --input
  • --ring
  • --radius

No type scale here on purpose. Radix and shadcn own colour, behaviour and states, and leave type to you.

5 things I steal

Type scale
Keep type out of the component library, so one kit fits many brands.
Colour tokens
Pair every surface with a '-foreground' variable. Swap the variables and the whole kit re-themes.
Spacing
One --radius variable sets every corner, so the whole kit changes shape at once.
Motion
Primitives expose open and closed states as data attributes, so you animate them with plain CSS.
States
Focus is a --ring variable and keyboard behaviour comes from Radix, so accessible states come free.

Do this with the toolkit

I add components with the shadcn CLI, then set the variables from my own token sheet instead of the default zinc.

read the source ↗ (Radix + shadcn, opens in a new tab)

My three token sheets

This site moves through three looks. These are the exact tokens each one uses.

[07]

Win95 / BR95

My Windows 95 token sheet. Grey bevels, pixel fonts and a black title bar, used in the opening act of this site.

specimen · MS Sans Serif pixel, with IBM VGA 8x16 for labels

  • pixel 32 · 32
  • pixel 16 · 16
  • ui 11 · 11
  • --w-desk#2c2c2c
  • --w-face#c0c0c0
  • --w-hi#ffffff
  • --w-shadow#808080
  • --w-dark#000000
  • --w-title#000000

Pixel sizes stay on the 8x16 grid: 16, 32, 48, 64.

5 things I steal

Type scale
Pixel fonts only at multiples of 16px, with font smoothing off, so every pixel stays sharp.
Colour tokens
Six greys do everything. The classic teal and navy are swapped for grey and black.
Spacing
Measured numbers from the real thing: an 18px title bar and a 28px taskbar.
Motion
Stepped, not eased. Windows jump like it's 1995.
States
Pressed is the bevel flipped: the four inset shadows swap light and dark.

Do this with the toolkit

I build the chrome by hand in CSS and check it frame by frame with the Playwright MCP.

see it on this site →

[08]

Black and white

The default look of this site. Near-black ground, seven greys, a pixel font for labels and a serif for big headings.

specimen · Newsreader for display, Schibsted Grotesk for reading, IBM VGA 8x16 for labels

  • display 64 · 64
  • pixel 32 · 32
  • reading 17 · 17
  • pixel 16 · 16
  • --v-bg#080808
  • --v-surface#0e0e0e
  • --v-line#1a1a1a
  • --v-steel#2c2c2c
  • --v-dim#8a8a8a
  • --v-soft#b0b0b0
  • --v-ink#f5f5f5

Reading text is 17px at 1.6 line height, at most 68 characters wide.

5 things I steal

Type scale
Three voices with three jobs: pixel for labels, serif for big moments, sans for reading.
Colour tokens
Seven greys, never raw hex in a component. Even the dimmest label passes AA on the ground.
Spacing
Hairline borders and 1px gaps between tiles do the separating, not shadows.
Motion
Every scroll animation sits inside a reduced-motion check. Reduced motion gets the final state at once.
States
Hover lifts a surface one grey step (line to steel). Focus is a visible outline, always.

Do this with the toolkit

I keep these as CSS variables in one file, and let GSAP and Lenis move things on top of them.

see it on this site →

[09]

Colour

The finale sheet. Six loud hues that arrive one at a time, then all at once.

specimen · Same families as black and white; the colour does the shouting

  • --c-1#ff2e00
  • --c-2#ff00a8
  • --c-3#7b2cff
  • --c-4#00b3ff
  • --c-5#00e676
  • --c-6#ffe600

Text on colour is always #080808 or #ffffff, whichever passes 4.5:1.

5 things I steal

Type scale
Don't add sizes for the colour act. Colour is already loud; the type stays the same.
Colour tokens
Six hues, each saturated to the edge, and nothing in between.
Spacing
Colour goes full bleed. A small swatch of a loud colour looks like a mistake; a whole field looks like a choice.
Motion
Introduce colour gradually: one hue in one piece, then fields, then everything.
States
On colour, text is only black or white, picked by contrast, never a tint.

Do this with the toolkit

I test each pair for 4.5:1 with the oklch picker and paint the fields with Paper Shaders.

see it on this site →