docs(adr-0023): charts and dashboards — d3 + observable plot #170

Merged
julien merged 1 commits from docs/adr-0023-charts-d3-observable-plot into main 2026-05-16 21:28:04 +02:00

1 Commits

Author SHA1 Message Date
Julien Gautier aa87db4362 docs(adr-0023): charts and dashboards — d3 + observable plot
CI / scan (pull_request) Successful in 3m30s
CI / commits (pull_request) Successful in 3m48s
CI / check (pull_request) Successful in 4m1s
CI / a11y (pull_request) Successful in 3m7s
Docs site / build (pull_request) Successful in 3m24s
CI / perf (pull_request) Successful in 8m13s
Records the decision to use D3 + Observable Plot, wrapped in a new
`libs/shared/charts/` lib, as the chart toolkit shared by
`portal-shell` and `portal-admin`. Implementation lands as a
separate chantier (`pnpm add` + `libs/shared/charts/` foundations +
3 starter components + audit-page integration).

The user's original ask cited D3 directly. The ADR honours that
preference but pairs D3 with Observable Plot — the same team's
higher-level layer (Mike Bostock / Observable Inc.). Plot turns
"standard charts" (bar / donut / line / stacked-bar / scatter) into
~50 LOC per type instead of the ~250 LOC each that raw D3 would
take. The shared lib's component contract stays uniform whether the
underlying technique is Plot or raw D3 — `<lib-bar-chart>`,
`<lib-heatmap>`, all expose the same `[data] / [caption] /
[description] / [ariaLabel] / [colorScheme]` signal-based shape.

Accessibility is enforced at the lib level (not bolted on per
chart): SVG `<title>` + `<desc>`, `<details>`-based tabular
fallback, colour-blind-safe palettes (Viridis / Cividis for
sequential, ColorBrewer Set2 for categorical), AA-contrast text,
`prefers-reduced-motion` gating. Six commitments, each unit-tested
so a sloppy contributor can't drop one silently.

Bundle impact (~65 KB gzip for the v1 vocabulary loaded on a
chart-bearing lazy chunk) stays well under ADR-0017's 100 KB lazy-
chunk cap via per-`d3-*` module imports.

Considered + rejected:
* D3 alone — 250 LOC per chart × 4-5 charts × consistent a11y
  posture across them all = sustained code investment before the
  first dashboard ships.
* Apache ECharts — 600 KB minified + canvas rendering with an
  `aria` plugin afterthought + JSON-config idiom is the furthest
  from the Angular-Signals direction the workspace runs on.
* Chart.js — narrower vocabulary than Plot, canvas-rendered with
  weaker out-of-the-box a11y, dark-mode integration brittle.

CLAUDE.md and `docs/decisions/README.md` updated in the same
change. ADR-0017 (perf budgets) and ADR-0016 (a11y baseline) are
referenced as the binding constraints; this ADR doesn't supersede
either, it operationalises both for the chart surface.
2026-05-16 21:22:41 +02:00