Bands / references / envelopes as LineChart reference layers
LineChart gains `bands` (shaded rectangles), `references` (horizontal / vertical / diagonal lines), and `envelopes` (signed-area fills between two bounds). Unlocks five editorial ideas from the cross-sport lab in one packet.
LineChart chart-apinew-primitiveseditorial
Context
Five distinct editorial chart ideas from the cross-sport lab (required-rate pace, Elo river, aging curve ±σ, rolling-form CI, Lorenz / Gini) all needed the same shared infrastructure:
- Axis-aligned zone bands (title race, relegation, confidence regions)
- Declarative horizontal / vertical / diagonal reference lines (manager changes, regression fits, equality diagonals)
- Signed-area fills between two bounds (actual vs pace, centre ±σ, Lorenz below equality)
Each had been catalogued as a separate 🟡 “small extension” in the roadmap. Building them independently would drift naming, semantics, and warning codes.
Decision
Ship a single chart reference layers packet delivering:
- Two new plot primitives —
ChartPlotAreaBands,ChartPlotAreaReferenceLines(withlayer="body" | "labels" | "both"for z-order control and Liang-Barsky segment clipping for diagonals). - LineChart extensions —
bands,references,envelopesprops. Envelopes come in three kinds:series-pair(two series as bounds),center-offset(centre series ± per-point upper/lower), andseries-to-reference(series vs a declared reference line — the Lorenz single-source-of-truth case). - Six helper factories —
managerEventRef,seasonEventRef,goalEventRef,diagonalFromLinear,envelopeCenterOffset,diagonalSeries. Typed withOmit<>so callers can’t override computed geometry fields. - Breaking migration — delete
eventsprop andLineChartEventInput/LineChartEventModeltypes. Replaced byreferences+ helpers. Meta fieldvalidSeriessplits intodataSeries(valid points) andvisibleSeries(not hidden).
Consequences
- Adversarial review loops surfaced 4 P0 findings before ship: band /
reference validation needed to live in compute (not primitive) so
warnings reach
model.meta.warnings;[envelope.truncated]must fire when a source series has dropped points; all-hidden charts must return empty state; diagonal references must clamp to their declaredfrom..tox-support (no silent extrapolation). - Primary consumer in
apps/sitemigrated in the same commit (events → references). No deprecation shims — this is pre-release v0.2. - Each envelope kind carries its own warning taxonomy
(
[envelope.unknown-series],[envelope.insufficient-points],[envelope.bounds-mismatch],[envelope.no-overlap],[envelope.vertical-reference],[envelope.inverted-bounds],[envelope.truncated],[envelope.unknown-reference]). XGTimeline’s existingbackgroundBandsmodel was NOT migrated — it’s intentionally preserved as a chart-specific concept tied to the compressed time-axis. If demand grows we can merge later.- Five cross-sport-lab ideas shipped to 🟢 ships-today status.