Jon CeronSenior Product Designer
EN

System

This page shows how this site's design system works: a Markdown spec for each component, the component built from it, and the checks that keep the two in sync. For a developer, it shows what to build from: every value is a token, and the build fails if a component uses a raw one. For a designer, it shows the reasoning behind the choices, such as why each text role has one size and every space is a multiple of 8px.

From spec to verified component

Spec

design-system/components/button.md

# Button

## Props
| Prop | Values |
| --- | --- |
| `href` | string |
| `type` | `submit`, `button` |
| `variant` | `primary` (default), `secondary`, `ghost` |
| `external` | boolean |
| `download` | boolean |
| `size` | `default`, `large` |

## Tokens
`--cmp-button-*` (height, padding-x, radius, font-weight, primary and secondary colors), `--sys-motion-*`.

Check

Theme: darklightTokens used: 21 of 21Hardcoded values: 0Body text on page: 15.9:117.5:1

Computed from the Button's CSS on every build. The build fails if it is not 0.

Color scales

The primitives behind the tokens: neutral for the dark theme, paper for the light theme, and the violet accent.

Token specdesign-system/tokens.md

Neutral, 12 steps

  • 1#1314161.0:1
  • 2#18191C1.0:1
  • 3#1E20241.1:1
  • 4#25272C1.2:1
  • 5#2C2F351.4:1
  • 6#3538401.6:1
  • 7#41454D1.9:1
  • 8#565B652.7:1
  • 9#7A808B4.6:1
  • 10#8A909B5.7:1
  • 11#B4B9C29.4:1
  • 12#EDEEF015.9:1

Paper, 12 steps (light theme)

  • 1#FCFCFD1.0:1
  • 2#F5F6F81.1:1
  • 3#ECEEF21.1:1
  • 4#E3E6EB1.2:1
  • 5#D9DDE31.3:1
  • 6#CDD2D91.5:1
  • 7#B9BFC81.8:1
  • 8#9AA1AD2.5:1
  • 9#7A808B3.9:1
  • 10#5C626C6.0:1
  • 11#3F444C9.6:1
  • 12#15171A17.5:1

Violet, the steps in use

  • 9#6E56CF3.4:1
  • 10#644CCB3.0:1
  • 11#B9A8FF8.9:1
  • a316%
  • a740%

Contrast is measured against the page background.

Why each text role has one size

Every role is a set of tokens: family, size, line height, weight and tracking. Display and section titles are fluid: they scale between two sizes with the viewport. Everything else is fixed, so body text follows the reader's browser font size.

  • Display

    Family
    Schibsted Grotesk
    Size
    2.25rem–3rem (36px–48px), fluid
    Line height
    1.05
    Weight
    600
    Tracking
    -0.035em
    Tokens
    --sys-type-display-size--sys-type-display-leading--sys-type-display-weight--sys-type-display-tracking--sys-font-sans
  • Section title

    Family
    Schibsted Grotesk
    Size
    1.75rem–2.5rem (28px–40px), fluid
    Line height
    1.15
    Weight
    600
    Tracking
    -0.02em
    Tokens
    --sys-type-title-size--sys-type-title-leading--sys-type-title-weight--sys-type-title-tracking--sys-font-sans
  • Heading

    Family
    Schibsted Grotesk
    Size
    1.25rem (20px)
    Line height
    1.3
    Weight
    600
    Tracking
    -0.01em
    Tokens
    --sys-type-heading-size--sys-type-heading-leading--sys-type-heading-weight--sys-type-heading-tracking--sys-font-sans
  • Lede

    Family
    Schibsted Grotesk
    Size
    1.25rem (20px)
    Line height
    1.65
    Weight
    400
    Tracking
    0
    Tokens
    --sys-type-lede-size--sys-type-lede-leading--sys-type-body-weight--sys-font-sans
  • Body

    Family
    Schibsted Grotesk
    Size
    1rem (16px)
    Line height
    1.65
    Weight
    400
    Tracking
    0
    Tokens
    --sys-type-body-size--sys-type-body-leading--sys-type-body-weight--sys-font-sans
  • Small

    Family
    Schibsted Grotesk
    Size
    0.875rem (14px)
    Line height
    1.5
    Weight
    400
    Tracking
    0
    Tokens
    --sys-type-small-size--sys-type-small-leading--sys-type-body-weight--sys-font-sans
  • Caption

    Family
    Schibsted Grotesk
    Size
    0.8125rem (13px)
    Line height
    1.5
    Weight
    400
    Tracking
    0
    Tokens
    --sys-type-caption-size--sys-type-caption-leading--sys-type-body-weight--sys-font-sans
  • Stat

    Family
    JetBrains Mono
    Size
    2.5rem (40px)
    Line height
    1.15
    Weight
    500
    Tracking
    0
    Tokens
    --sys-type-stat-size--sys-type-stat-leading--sys-type-label-weight--sys-font-mono

Why every space is a multiple of 8px

One step is 8px, written in rem. A half step (4px) is reserved for tight pairs such as an icon and its label. Components never use a step directly: they use the semantic names in the last column.

SteprempxScaleUsed as
space.half0.25rem4pxspace.hairline-gap
space.10.5rem8pxspace.stack-xs
space.21rem16pxspace.gutterspace.stack-sm
space.31.5rem24pxspace.stack-mdsize.swatch
space.42rem32pxspace.gutterspace.stack-lg
space.52.5rem40pxsize.control-heightsize.mark-height
space.63rem48pxspace.sectionspace.stack-xlsize.logo-heightsize.chip-heightsize.control-height-large
space.73.5rem56pxspace.section
space.84rem64pxsize.header-height
space.105rem80pxNot referenced by a semantic token
space.126rem96pxsize.scroll-offset
space.168rem128pxNot referenced by a semantic token