A11y theme modes (color-blind, low-vision)
Two additional theme modes alongside Verge light/dark — `color-blind` (deuteranopia-safe palette swap) and `low-vision` (text size +20%, font-weight ≥500, contrast floor AAA). User opt-in via Settings; persisted in `koder.a11y_mode`. Mirrors Duet (LocalTapiola) practice.
Spec — Accessibility theme modes
*tatus* v0.1.0 — Draft. Companion to Verge v0 (
specs/themes/verge.kmd). v0 introduces the SELECTORS + token overrides; per-product implementation inkoder_kit/koder_web_kitis sub-ticketed.
R1 — Two new modes
| Mode | Selector | Default | Purpose |
|---|---|---|---|
| color-blind | [data-a11y-mode="color-blind"] |
OFF | Deuteranopia/protanopia |
| low-vision | [data-a11y-mode="low-vision"] |
OFF | Larger text, heavier weight, AAA-floor contrast |
Modes compose with light/dark ([data-theme="dark"][data-a11y-mode="color-blind"]).
R2 — Color-blind palette deltas
Verge v0 (Adwaita-based) currently exposes only
bg / surface / surface-2 / text / text-muted / accent / accent-on / border / focus. Semantic status tokens (success / danger / warning) are NOT yet ratified ininternal/kinds/verge.go. Until they are, color-blind mode v0 ships *he selector only*— the swap table below is the contract semantic tokens MUST honor when added.
| Verge role (proposed) | Default light | color-blind light | Default dark | color-blind dark |
|---|---|---|---|---|
--kdr-accent |
#1f3a93 (blue base) | unchanged | #6fa3ff | unchanged |
--kdr-success (TBR) |
#1a7f37 (green) | *2563eb (blue)* | #46c476 | *60a5fa (blue)* |
--kdr-danger (TBR) |
#cf222e (red) | *ea7c34 (orange)* | #ff7b7b | *f59e0b (amber)* |
--kdr-warning (TBR) |
#d29922 (amber) | *a855f7 (violet)* | #f0c674 | *c084fc (violet)* |
Rationale: deuteranopia-safe pairs use blue/orange axis where the typical red/green axis fails.
Followup ticket required in `tools/designgen to ratify
-drsuccess / -kdrdanger / -kdr-warning` tokens in Verge before the color-blind mode can carry semantic meaning.
R3 — Low-vision deltas
| Token | Default | low-vision |
|---|---|---|
--kdr-fs-base |
16px | 19px (+20%) |
--kdr-line-height (TBR) |
1.5 | 1.6 |
--kdr-font-weight-min (TBR) |
400 | 500 |
--kdr-contrast-floor (TBR) |
4.5 (WCAG AA) | 7.0 (WCAG AAA) |
Tokens marked (TBR) (to be ratified) are not yet in Verge v0; their introduction is gated on a followup Verge tokenset expansion ticket. --kdr-fs-base already exists and IS swapped in v0 of this spec — text-scaling support ships immediately.
R4 — Implementation contract
base.cssships[data-a11y-mode="color-blind"]and[data-a11y-mode="low-vision"]selectors at the same cascade level as[data-theme="dark"]. Tokens cascade through; products that usevar(--kds-color-...)get the swap for free.- Settings drawer ratchets the 4-segment control:
default/color-blind/low-vision/both. Last option applies both selectors. - localStorage key
koder.a11y_modepersists choice; anti-flashscript sets the
data-a11y-modeattr on<html>before first paint (same pattern asdata-theme). tools/design-gen/cmd/verge-contrast-auditextends to also auditpairs under both new modes; CI fails on regressions.
R5 — Live demo
/<locale>/themes/a11y-modes/ renders a sample card (heading + body + button + success + danger pills) in 4 modes sidebyside.
R6 — Nutrition-labels integration
Products that ship working colorblind / lowvision support SHOULD declare in their koder.toml:
[a11y_labels]
color-blind-mode = "supported"
high-contrast = "supported" # if also adding forced-colors
dynamic-type = "supported" # implied by low-visionPer specs/accessibility/nutrition-labels.kmd.
Não-escopo
- Auto
detect from OS (forcedcolors media query is separate spec). - Per
locale typography overrides beyond size/weight (e.g., scriptspecific weight rebalancing for CJK).
- Windows high-contrast bridge (separate spec).