Open DS

Color

Five questions every design system answers about color. These are Dense data’s answers, and each one points back to the reasons that chose it.

View all 41 color tokens ↓

The reasons this scheme answers from

  • R1BrandPrecise, quiet
  • R2Tasks and flowsScan and compare, constantly
  • R3Business and productRuns daily operations, one
  • R4OutcomesTime on task, acting on the wrong record

Question 1

Which color roles does it need?

  • Surface, text, action and status (chosen)
  • Those and brand accents

Why Dense data picks it: Surface, text, action and status cover an operations tool.

becauseR1

surface
text
border
action
status
category
disabled

Question 2

How many emphasis levels do actions need?

  • Two
  • Three (chosen)
  • Four

Why Dense data picks it: One primary per view; the rest step back.

becauseR2

slate light8
violet light3
black light1
blue light3
green light2
amber light2
red light2

Question 3

How is the palette defined?

  • Neutrals and one brand ramp (chosen)
  • Shared neutrals, a ramp per brand

Why Dense data picks it: One product, one brand ramp on cool neutrals.

becauseR3

  • Neutrals and one brand ramp
  • from color.slate.light
  • from color.violet.light
  • from color.black.light
  • from color.blue.light
  • from color.green.light
  • from color.amber.light
  • from color.red.light

Decisions point at primitives, so the rule lives in one place.

Question 4

How saturated is the palette?

  • Muted (chosen)
  • Balanced
  • Vivid

Why Dense data picks it: Muted color keeps attention on the data.

becauseR1

  • surface
    canvas
    → color.slate.light.50· dark → color.slate.dark.0
    default
    → color.slate.light.0· dark → color.slate.dark.50
    raised
    → color.slate.light.0· dark → color.slate.dark.100
    sunken
    → color.slate.light.100· dark → color.slate.dark.100
    selected
    → color.violet.light.100· dark → color.violet.dark.100
    inverse
    → color.slate.light.900· dark → color.slate.dark.900
    scrim
    → color.black.light.scrim· dark → color.black.dark.scrim
  • text
    primary
    → color.slate.light.900· dark → color.slate.dark.900
    secondary
    → color.slate.light.700· dark → color.slate.dark.500
    muted
    → color.slate.light.600· dark → color.slate.dark.400
    inverse
    → color.slate.light.0· dark → color.slate.dark.50
    on-action
    → color.slate.light.0· dark → color.slate.dark.0
    link
    → color.violet.light.700· dark → color.violet.dark.700
  • border
    default
    → color.slate.light.200· dark → color.slate.dark.100
    strong
    → color.slate.light.500· dark → color.slate.dark.300
    focus
    → color.violet.light.600· dark → color.violet.dark.700
  • action
    primary.@
    → color.violet.light.600· dark → color.violet.dark.700
    primary.hover
    → color.violet.light.700· dark → color.violet.dark.800
    secondary.@
    → color.slate.light.0· dark → color.slate.dark.50
    secondary.hover
    → color.slate.light.100· dark → color.slate.dark.100
  • status
    info.@
    → color.blue.light.700· dark → color.blue.dark.700
    info.subtle
    → color.blue.light.100· dark → color.blue.dark.100
    success.@
    → color.green.light.700· dark → color.green.dark.700
    success.subtle
    → color.green.light.100· dark → color.green.dark.100
    warning.@
    → color.amber.light.700· dark → color.amber.dark.700
    warning.subtle
    → color.amber.light.100· dark → color.amber.dark.100
    danger.@
    → color.red.light.700· dark → color.red.dark.700
    danger.subtle
    → color.red.light.100· dark → color.red.dark.100
  • category
    1.@
    → color.violet.light.600· dark → color.violet.dark.700
    1.subtle
    → color.violet.light.100· dark → color.violet.dark.100
    2.@
    → color.blue.light.600· dark → color.blue.dark.700
    2.subtle
    → color.blue.light.100· dark → color.blue.dark.100
    3.@
    → color.green.light.700· dark → color.green.dark.700
    3.subtle
    → color.green.light.100· dark → color.green.dark.100
    4.@
    → color.amber.light.700· dark → color.amber.dark.700
    4.subtle
    → color.amber.light.100· dark → color.amber.dark.100
    5.@
    → color.slate.light.500· dark → color.slate.dark.700
    5.subtle
    → color.slate.light.100· dark → color.slate.dark.100
  • disabled
    text
    → color.slate.light.500· dark → color.slate.dark.500
    surface
    → color.slate.light.100· dark → color.slate.dark.100
    border
    → color.slate.light.200· dark → color.slate.dark.200

Question 5

Where does color carry meaning first?

  • Status in tables (chosen)
  • Links and actions
  • Brand moments

Why Dense data picks it: Color earns its place by marking late and failed records.

becauseR4

  • button · 13 keys
  • input · 8 keys
  • control · 3 keys
  • badge · 10 keys
  • card · 2 keys
  • table · 3 keys
  • tabs · 3 keys
  • overlay · 4 keys

When to use

  • A selected row or itemUse: color.surface.selected. Not: color.action.primary as a fill. A light tint shows selection without hiding the data.
  • An error messageUse: color.status.danger with an icon. Not: color.status.warning. Red always means fix this, and the icon says it without color.
  • A linkUse: color.text.link. Not: color.action.primary. Links and buttons look different, so people know which one navigates.
  • A statusUse: Badge with a subtle fill, an icon and a word. Not: A full-strength fill. Subtle fills let many statuses share one table.
  • The action that completes the taskUse: Button primary, one per view. Not: Two primaries side by side. One primary makes the committing action obvious.
  • An alternative or cancelUse: Button secondary. Not: Button ghost. Cancel must be easy to find next to the primary.
  • Delete or removeUse: Button secondary, then confirm in a dialog. Not: Button primary as the first step. Deleting is rare and costly; a confirm step catches mistakes.

All color tokens

41 tokens · each decision and the primitive it points to

  • color.slate.light · 8color.slate.light.50#F7F8FAcolor.slate.light.0#FFFFFFcolor.slate.light.100#EEF1F5color.slate.light.900#161B23color.slate.light.700#3D4655color.slate.light.600#535D6Dcolor.slate.light.200#DDE2EAcolor.slate.light.500#6B7585
  • color.violet.light · 3color.violet.light.100#EEEDFEcolor.violet.light.700#3B31B0color.violet.light.600#4B3FD9
  • color.black.light · 1color.black.light.scrim#0000008C
  • color.blue.light · 3color.blue.light.700#083C93color.blue.light.100#E1ECFFcolor.blue.light.600#0B4FC0
  • color.green.light · 2color.green.light.700#1F7A3Acolor.green.light.100#E3F4EA
  • color.amber.light · 2color.amber.light.700#8A5600color.amber.light.100#FFF3D6
  • color.red.light · 2color.red.light.700#C42B2Bcolor.red.light.100#FDE7E7
  • Decisions · 41color.surface.canvas{color.slate.light.50}color.surface.default{color.slate.light.0}color.surface.raised{color.slate.light.0}color.surface.sunken{color.slate.light.100}color.surface.selected{color.violet.light.100}color.surface.inverse{color.slate.light.900}color.surface.scrim{color.black.light.scrim}color.text.primary{color.slate.light.900}color.text.secondary{color.slate.light.700}color.text.muted{color.slate.light.600}color.text.inverse{color.slate.light.0}color.text.on-action{color.slate.light.0}color.text.link{color.violet.light.700}color.border.default{color.slate.light.200}color.border.strong{color.slate.light.500}color.border.focus{color.violet.light.600}color.action.primary.@{color.violet.light.600}color.action.primary.hover{color.violet.light.700}color.action.secondary.@{color.slate.light.0}color.action.secondary.hover{color.slate.light.100}color.status.info.@{color.blue.light.700}color.status.info.subtle{color.blue.light.100}color.status.success.@{color.green.light.700}color.status.success.subtle{color.green.light.100}color.status.warning.@{color.amber.light.700}color.status.warning.subtle{color.amber.light.100}color.status.danger.@{color.red.light.700}color.status.danger.subtle{color.red.light.100}color.category.1.@{color.violet.light.600}color.category.1.subtle{color.violet.light.100}color.category.2.@{color.blue.light.600}color.category.2.subtle{color.blue.light.100}color.category.3.@{color.green.light.700}color.category.3.subtle{color.green.light.100}color.category.4.@{color.amber.light.700}color.category.4.subtle{color.amber.light.100}color.category.5.@{color.slate.light.500}color.category.5.subtle{color.slate.light.100}color.disabled.text{color.slate.light.500}color.disabled.surface{color.slate.light.100}color.disabled.border{color.slate.light.200}

Decisions reference primitives, so changing one primitive updates every decision and component that uses it.

Color in Dense data: muted. Muted color keeps attention on the data. Color earns its place by marking late and failed records.