User Interface — Explorer, Filters & Library#
Implementation status: Extended (display layer; no engine-parity
impact — every component on this page is presentation over the documented
engine)
Source: src/components/ScenarioExplorer.tsx,
src/components/RouteFilterPanel.tsx, src/map/route-filter.ts,
src/map/RouteMapPanel.tsx, src/components/ScenarioLibrary.tsx,
src/components/ContributionCards.tsx,
src/state/custom-flags.ts, src/components/SidebarPillars.tsx
Test evidence: tests/route-filter.spec.ts (14),
tests/preset-collections.spec.ts (5), tests/custom-flags.spec.ts
(4), tests/display-logic.spec.ts (9)
Route & class display filters#
A compact “Routes & Classes” popover (RouteFilterPanel — CASCADE
Location/Route/Aircraft filter parity, single-panel form) filters the
24-route synthetic dataset (Air Traffic Dataset): four size-class master
toggles (regional / single-aisle / widebody / freighter), All/None
shortcuts, and a searchable per-route include list (case-insensitive match
over route id and airport codes). All logic lives in the pure module
src/map/route-filter.ts; the panel is a thin shell.
The filter computes a coverage fraction — included 2019 flights ÷ total 2019 flights over the synthetic set. Honest-scope rule: this is a display filter only, never route-level modelling. When the filter is active (fraction < 1), the explorer chart multiplies gross BAU by the coverage fraction and shows an explicit warning label:
“Filtered view (scaled): Traffic (BAU) is multiplied by the route-coverage fraction (×f) — display-only scaling over the synthetic route set, not route-level modelling. Reductions, net and SBTi are unchanged global aggregates.”
Route map panel#
RouteMapPanel draws the synthetic network on a free, token-less
basemap (MapLibre GL + CARTO dark-matter style): great-circle arcs from
geodesic.ts:greatCircleArc over the route-airports.ts coordinates,
coloured per size class, with filter-excluded routes dimmed (kept faintly
visible for orientation). The panel carries the same honest caption —
“Great-circle arcs over the 24-route synthetic dataset — display filter
only, not route-level modelling” — plus a coverage readout (routes and
share of 2019 flights). It mounts only while the Map tab is active, so the
WebGL context exists only when visible, and unknown airport codes skip an
arc rather than crash the view.
Scenario library#
ScenarioLibrary is a full-screen overlay page (CASCADE
scenario-library parity) opened from the explorer header:
a featured card (the most complete preset,
FEATURED_PRESET_KEY);collection tabs — All plus the groups from
data/preset-collections.ts(drift-proof: collection tests guard preset/collection consistency);preset cards showing ambition-level chips (per-pillar n/5), source basis and end year, loaded through the same callback the preset dropdown uses (no duplicated apply logic); the currently loaded preset is flagged;
“Create new scenario” resets to the canonical defaults.
All library scenarios run to 2050 (the default engine horizon; Traffic Growth).
Contribution cards#
The right rail (ContributionCards, CASCADE right-rail parity) shows a
primary “CO₂ Emissions in 2050” card (kpis.net2050, with BAU and SBTi
comparison values) followed by one card per reduction lever — aircraft,
operations, energy, offsets & removals — showing the 2050 abatement (Mt
CO₂-eq) and its percentage of the total reduction. Card accent colours are
lifted verbatim from the emissions-wedge segment colours so the rail and
the chart always agree.
Custom-settings badges#
Each sidebar pillar carries a “Custom settings applied” chip when the live
scenario deviates from the canonical defaults (custom-flags.ts;
CASCADE parity). The detection is derived, never hand-maintained: lever →
field membership is resolved by regex over the generated scenario-schema
keys; for the core numeric fields tracked by url-state.ts:DEFAULTS a
lever is flagged when a value differs from default, and for any other
schema field its presence counts as a customisation (URL decode and UI
patches are both sparse, so such fields only exist when explicitly set).
The chip tooltip lists the differing fields.
Known deviations / limitations#
The route filter and map are display-only; they do not re-run the engine per route and the scaled-BAU view is labelled as such.
Custom-settings badges diff against engine defaults, not against the loaded preset; preset-written parameters therefore register as customisations.
The scenario library is an overlay view without routing; scenario state underneath is untouched.