Skip to content

Color palette

These are the primitive color ramps — the bottom layer of the four-layer token model. Every semantic, component, and theme token ultimately resolves to one of the shades below.

Each ramp runs the standard 50–950 scale. The five neutral ramps add a tuned 350 step — the dark-theme text-muted shade, chosen so muted text keeps ≥ 4.5:1 contrast even on muted-bg (the ramp’s 700) surfaces. The gray ramp is the project’s default neutral; slate / zinc / neutral / stone are the alternative neutrals offered by the Theme builder. The accent / status hues back the built-in data-color themes and the fixed semantic info / success / warning / error colors.

The seven chromatic ramps are generated, not hand-picked. Each is one hue angle run through a shared ladder, written as oklch(L C H):

  • L comes from the step and is identical across hues, so 600 means the same darkness whether the hue is blue or amber.
  • C is an absolute target per step, clamped to whatever that hue can actually hold in sRGB at that lightness. Chroma as a fraction of the gamut maximum would trace the gamut boundary instead, whose shape swings by hue — green’s is widest at high lightness, so a fixed fraction makes green.200 more colorful than green.500 and the light tints come out neon.
  • H is constant down the ramp, so a ramp never drifts in hue.

That is what lets the accent themes share one shape and one foreground rule. scripts/build-ramp.mjs regenerates the values and test/ramp.test.mjs asserts the committed tokens still match the ladder.

The five neutral ramps are not generated. They were already perceptually even — lightness spread of at most 1.8 points at any step, against 18.3 for the chromatic ramps before this change — and dark mode is built entirely from them, so they were left alone.

Swatches are labelled with their sRGB hex for pasting into other tools; hover a swatch to see the token path and its authored oklch() value.

white oklch(1 0 0)black oklch(0 0 0)

Neutrals

color.gray
50#f9fafb
100#f3f4f6
200#e5e7eb
300#d0d5dd
350#a7aeb9
400#9ca3af
500#6b7280
600#4b5563
700#374151
800#1f2937
900#111827
950#030712
color.slate
50#f8fafc
100#f1f5f9
200#e2e8f0
300#cbd5e1
350#a1aec1
400#94a3b8
500#64748b
600#475569
700#334155
800#1e293b
900#0f172a
950#020617
color.zinc
50#fafafa
100#f4f4f5
200#e4e4e7
300#d4d4d8
350#acacb4
400#a1a1aa
500#71717a
600#52525b
700#3f3f46
800#27272a
900#18181b
950#09090b
color.neutral
50#fafafa
100#f5f5f5
200#e5e5e5
300#d4d4d4
350#adadad
400#a3a3a3
500#737373
600#525252
700#404040
800#262626
900#171717
950#0a0a0a
color.stone
50#fafaf9
100#f5f5f4
200#e7e5e4
300#d6d3d1
350#b2ada9
400#a8a29e
500#78716c
600#57534e
700#44403c
800#292524
900#1c1917
950#0c0a09

Accent & status hues

color.blue
50#f0f5ff
100#e2ebff
200#cadbfe
300#a8c4fe
400#77a2fd
500#477cfd
600#2c60e9
700#1f4cc7
800#163ba2
900#102d79
950#091b48
color.indigo
50#f2f4ff
100#e6eaff
200#d1d8fe
300#b5bffe
400#8f9afd
500#6c71fd
600#5755e7
700#4642c6
800#3733a0
900#282678
950#171747
color.violet
50#f5f3ff
100#ebe8ff
200#dbd4fe
300#c6b9fe
400#a98ffd
500#8f65f3
600#7947dd
700#6435bd
800#502899
900#3b1f72
950#221344
color.fuchsia
50#fdf1f9
100#fae4f3
200#f5cdea
300#f0aadd
400#e17ac9
500#cd48b3
600#b5239c
700#981083
800#7b0769
900#5c0a4e
950#37092e
color.rose
50#fff1f1
100#ffe4e4
200#fecccd
300#feaaac
400#f8767f
500#e73e56
600#cd0c3e
700#aa0832
800#880526
900#68021b
950#3f050f
color.red
50#fff2f0
100#ffe4e0
200#fecdc7
300#feaba1
400#f8786c
500#e7413a
600#ce0e18
700#ac0812
800#8a050c
900#690307
950#3f0605
color.orange
50#fff2ec
100#fee5d9
200#fcd0b9
300#fcb088
400#f2823f
500#d2600a
600#ae4f07
700#904004
800#733203
900#582401
950#371300
color.amber
50#fcf4ea
100#fae8d5
200#f5d5b1
300#f0b877
400#e09110
500#b8760b
600#986107
700#7e4f04
800#643e03
900#4c2e01
950#2e1a00
color.lime
50#f3f7eb
100#e8efd7
200#d5e1b6
300#bbcf81
400#98b227
500#7b920b
600#657907
700#536305
800#414f03
900#303b01
950#1c2300
color.green
50#ecf9f2
100#d9f2e5
200#b8e8d0
300#81dab1
400#14c189
500#0e9e6f
600#0a835b
700#066c4b
800#04553a
900#02402b
950#012718
color.teal
50#eaf9f8
100#d4f2f1
200#aee8e5
300#67dad6
400#14bcb9
500#0e9a97
600#0a7f7d
700#066966
800#045351
900#023e3d
950#002524

When you author a custom theme (see Authoring your own theme), point a DTCG token at a primitive by its path:

{
"color": {
"action": {
"primary": {
"bg": { "$type": "color", "$value": "{primitive.color.violet.600}" }
}
}
}
}

Hover any swatch above to see its exact {primitive.color.*} path and hex. The build resolves the reference to the concrete value; the primitive itself is never emitted.