Pular para o conteúdo

Primitive color palette

themes specs/themes/palette.kmd

The PRIMITIVE color tier of the Koder Design System: named hues, each with an OKLCH tonal ramp (50–900). It is the single machine-readable pool of color steps that semantic roles (`color-roles.kmd`), product icons (`icons/products.kmd`) and — if RFC-007 ratifies — the seed layer all draw FROM. Replaces ad-hoc per-asset hexes with references like `blue-600`. Does NOT presuppose the seed/map/alias algorithm (RFC-007 is draft/deferred); it only supplies the primitives. Source of truth: `meta/brand/koder-design/palette/primitives/primitives.json` (DTCG).

Quando esta spec se aplica

Triggers primários

Todos os triggers

Corpo da especificação

Spec — Primitive color palette

Tier: primitive (the "wheel"). This is the layer below semantic roles. A role like accent or success (color-roles.kmd) and a product icon's dominant color (icons/products.kmd) MUST resolve to a named step here (e.g. blue-600), never a free hex. This kills the "which blue / how deep" guesswork by making every color a reference.

Relationship to the existing color specs (no duplication)

LayerOwner specWhat it holds
Primitive (this spec)palette.kmd + primitives.jsonNamed hues × tonal ramps 50–900. The raw pool.
Semantic (map)color-roles.kmdtext / accent / error / success / warning / info … — each role POINTS to a primitive step. Unchanged; this spec only gives it concrete steps to point at.
UI palette (Verge)verge.kmdIn-product surfaces. Verge accent #3584E4blue-500.
Editorial paletteeditorial-palette.kmdMarketing/landing only (scope split per its §R1 — NOT merged here). Gains ramps the same way if/when needed.
Seed/map/alias algorithmrfcs/design-RFC-007 (DRAFT, deferred)IF ratified, its seed tokens draw from this primitive pool. This spec does not adopt the algorithm — it is orthogonal and useful regardless.

R1 — Method (OKLCH, gamut-clipped)

Ramps are generated in OKLCH (Björn Ottosson) for perceptual uniformity — equal numeric steps look equally far apart, fixing the uneven-brightness jumps of naïve HSL. Each named hue is anchored by a 600-ish hex; the generator fixes a perceptual-lightness target L per step and scales chroma along a peak-in-the-middle curve, then clips chroma into the sRGB gamut where a step would otherwise be unrepresentable. Resolved sRGB hex is persisted (with the source oklch in $extensions) so non-CSS targets (RFC-006: 7 languages) get hex directly. Generator: palette/primitives/generate_primitives.py.

Per-step perceptual lightness L (OKLCH, 0–1):

Step50100200300400500600700800900
L.97.94.88.81.72.64.56.47.38.28

R2 — Named hues (the wheel)

11 hues: one neutral (slate) + a 10-hue chromatic wheel covering every product/domain need. Full step values + WCAG contrast live in primitives.json; this table is the symbolism/derivation index.

HueAnchor (~600)DerivationSymbolism / use
slate#5b6675neutral cool graySurfaces, text, borders, dividers — the structural backbone.
blue#3584E4verge.accent (Adwaita)Brand/UI primary; products domain; info. The default action color.
indigo#4f46e5verge.blue → indigoDepth/platform; cloud/compute; deep-blue sibling.
violet#7c3aededitorial.violet/plumAI / data / creative; services domain; flagship signature option.
magenta#db2777editorial.magentaPlayful / navigation / discovery accents.
red#dc2626verge.rederror/danger (semantic); mail/urgent; high-attention.
orange#ea580cverge.orangeWarm action / craft; coral/mail gradient partner.
amber#f59e0bverge.yellow → amberwarning (semantic); time/calendar; meta domain warmth.
green#16a34averge.greensuccess (semantic); hub/store; growth / go.
teal#0d9488verge.green → tealengines domain; maps/location; fresh / raw power.
cyan#0891b2verge.blue → cyaninfra domain; operation / observability; cool signal.

R3 — Usage matrix (which step goes where)

A band discipline that holds across all hues (because OKLCH L is constant per step). Light theme shown; dark theme mirrors (swap the band, keep the hue).

Step bandRoleExamples
50–100Subtle fills / tintsBanner backgrounds, hovered-row tint, selected-tint, *-bg role variants.
200–300Hairlines / disabledBorders, dividers, disabled controls, skeletons.
400–500Secondary / hoverSecondary accents, hover states, gradient light end, illustration mid-tones.
600Primary on lightaccent, primary buttons, links, dominant icon fill. Floor: AA (≥4.5) on white.
700–800Pressed / deepPressed/active states, gradient deep end, emphasis on tinted bg.
900Ink / textBody text on light, max-emphasis headings, deepest gradient stop.

Contrast gate (hard): any text/icon step on its background MUST meet WCAG AA (4.5 normal / 3.0 large). primitives.json carries contrast_on_white / contrast_on_black per step; kicon validate and koder-spec-audit themes enforce. Roles in color-roles.kmd keep their existing contrast targets — this spec just makes the chosen step explicit.

R4 — Domain → signature hue (RFC-003 L1)

Each L1 domain gets a signature hue for domain-level identity (domain landings, console chrome, docs section accents). This is the systematic anchor; it does NOT force every product in the domain to that hue (see R5).

DomainHueRationale
products/blueUser-facing apps; the Verge brand-action color.
services/violetAPI / AI / data-narrative.
engines/tealEmbedding / raw power.
infra/cyanOperation / observability.
meta/amberHuman reading: docs, brand, sites — warmth.

R5 — Product → hue alias (icon dominant color)

Product launcher icons need mutual distinctiveness on a home screen, so each product picks its own wheel hue (it does not collapse to its domain hue). What makes them read as one family — the #1 gap in #038 — is not a shared hue but a shared band rule:

Icon family rule. Dominant fill = <hue>-600. Icon gradient runs <hue>-700 (deep, bottom) → <hue>-500 (mid) → <hue>-400 (light, top). White symbol in negative space. All hues sit in the same OKLCH lightness band, so seven different hues still look like siblings. This supersedes the ad-hoc hexes of the 2026-06 proposal and refines icons/products.kmd §1 ("cor derivada da paleta Koder") from prose to a concrete reference.

ProductHueDominantGradient (deep → light)
Koder Driveblueblue-600blue-700 → blue-500 → blue-400
Koder Hubgreengreen-600green-700 → green-500 → green-400
Koder Mailredred-600red-700 → red-500 → orange-400
Koder Cloudindigoindigo-600indigo-700 → indigo-500 → violet-400
Koder Maptealteal-600teal-700 → teal-500 → green-400
Koder Calamberamber-600amber-700 → amber-500 → amber-400
Koder Kruzevioletviolet-600violet-700 → violet-500 → magenta-400

The single-hue-per-product rule (products.kmd §1) stays; the optional analogous-neighbor light end (e.g. Mail → orange-400) is the only sanctioned two-tone, and stays within one wheel-neighbor — not Google's full polychromy. New products: pick a free wheel hue; record it here.

R6 — Machine-readable source of truth

palette/primitives/primitives.json (DTCG, koder.* extensions) is authoritative; palette.kmd is the human mirror. Regenerate with generate_primitives.py (pure-Python OKLCH, no deps). Distribution to the 7 token languages rides RFC-006; Figma sync rides RFC-005. Never hand-edit the JSON hexes — change the anchors/curve and regenerate.

Open decisions (owner sign-off → ratify)

  • Ratify the 11-hue set + L-band targets (or tune).
  • Confirm domain→hue map (R4) and product→hue map (R5).
  • Whether color-roles.kmd should be migrated to reference primitive steps now, or in a follow-up (this spec is non-breaking until then).

Sign-off

ItemState
Method (OKLCH + gamut clip)drafted 2026-06-03
Primitive ramps generatedprimitives.json (11×10)
Owner ratification✅ 2026-06-03 (owner)

Referências