Skip to content

Color roles

themes specs/themes/color-roles.kmd

Semantic color role taxonomy — the mapping from concrete tokens (bg, surface, accent, error, etc.) to the UI elements that use each. Material parity (`/styles/color/roles`). Companion to `themes/color-schemes.kmd` (which defines the actual colors) and `foundations/elements.kmd` (which says which family uses which role).

When this spec applies

Primary triggers

All triggers

Specification body

Spec — Color roles

Facet Visual do Koder Design. Material parity: https://m3.material.io/styles/color/roles.

A role is a semantic slot ("primary action accent", "page background"). A token is the concrete value bound to that role in the current theme. Roles stay constant across themes; tokens vary.

R1 — The 18 canonical roles

Organized by the 5 element families from foundations/elements.kmd:

Surface roles

RoleTokenUse
bg--kdr-bgPage background
surface--kdr-surfaceCards, sheets, raised containers
surface-variant--kdr-surface-2Recessed/inset surfaces (search box, code block)
surface-inverseinverse-bgSnackbars, tooltips (dark on light pages, light on dark)

Content roles

RoleTokenUse
text--kdr-textPrimary text on bg / surface
text-muted--kdr-text-mutedSecondary text, captions, helper text
text-subtle--kdr-text-subtleDisabled text, placeholders
text-on-accent--kdr-accent-onText on accent-filled surfaces

Control roles

RoleTokenUse
accent--kdr-accentPrimary action button, active link
accent-strong--kdr-accent-strongHover/pressed state of accent
accent-on--kdr-accent-onForeground on accent (text/icon)
accent-tintaccent at 12% opacitySelected row background, focus halo

Status roles

RoleTokenUse
error--kdr-errorError state border/text
error-bg--kdr-error-bgError banner background (subtle tint)
warning--kdr-warningWarning state border/text
success--kdr-successConfirmation badge, valid input
info--kdr-infoInformational banner

Decoration roles

RoleTokenUse
border--kdr-borderContainer borders, dividers
border-strong--kdr-border-strongEmphasis borders (focused container)
focus--kdr-focusKeyboard focus ring color
selection--kdr-selectionText selection bg / row selection bg

R2 — Role binding contract

Every koder_kit widget MUST bind colors via roles, not raw hex:

// ❌
Container(color: Color(0xFF3B5BFD)) // hardcoded

// ✅
Container(color: KoderTheme.of(context).accent)

The theme exposes a typed KoderColorRoles struct (planned) with one getter per role. Widget code never references tokens by string.

R3 — Inversion in dark mode

Roles flip meaning between light and dark themes via the token system, not via per-widget logic. Example:

RoleLight theme tokenDark theme token
bg#FFFFFF#0B1220
text#0B1220#E7ECF5
accent#3B5BFD#7E97FF (lighter for dark bg legibility)

Widget code stays the same; the theme rebinds the tokens.

R4 — Contrast requirements

Per color-schemes.kmd § AAA contrast, role bindings must satisfy:

PairMin ratio
text/bg, text/surface7.0 (AAA Normal)
text-muted/bg4.5 (AA)
accent-on/accent4.5 (AA)
error/error-bg4.5
focus/bg3.0 (UI element contrast)

high_contrast preset tightens all to ≥ 7.0.

R5 — Forbidden bindings

  • ❌ Body text on accent background (use accent-on instead)
  • text-muted for primary action labels (use text or accent-on)
  • ❌ Body text in error color (red text outside error context is alarming)
  • ❌ Custom hex on user-facing surface without going through a role

R6 — When to add a new role

Adding a role is an architectural decision (impacts every theme). Threshold:

  • Needed by ≥ 2 widgets
  • Not expressible via existing role + opacity modifier
  • Has a stable semantic meaning across themes

Process: propose via PR with the binding added to all 12 color scheme presets simultaneously (per color-schemes.kmd Catalog).

  • color-schemes.kmd — concrete tokens per preset
  • light-dark.kmd — light/dark switching behavior
  • foundations/elements.kmd — which family uses which roles
  • interaction/states.kmd — overlay/state colors derive from roles

References