feat(themes): add a sequential scale; fix the magnitude ramps (Phase 2a) - #4611
feat(themes): add a sequential scale; fix the magnitude ramps (Phase 2a)#4611Yeraze wants to merge 1 commit into
Conversation
Folds in the widget-ramp bug. Investigating it corrected my own framing: only ONE of the three widgets is a hop ramp. - HopDistributionWidget IS hops, and hardcoded a private 7-colour list that disagreed with the map (2 hops was blue there, teal here) and ignored `overlayColors.hopColors` — the gradient the user can actually configure and the map honours. Now calls the shared `getHopColor(hop, overlayColors.hopColors)`. - DistanceDistributionWidget indexes by position in a distance histogram and HopDistanceHeatmapWidget by cell density. Those are MAGNITUDE, not hops. Pointing them at hopColors would have mislabelled distance buckets as hop counts; pointing them at --chart-N would have repeated the category error Phase 1 fixed. So this adds the third kind of colour the file was missing. A role says what a colour MEANS; a categorical slot only has to differ from its neighbours; a sequential step has to READ AS ORDERED. --seq-1..5 are built with color-mix from the accent rather than picked from the palette, which buys what the palette cannot: monotonic by construction, incapable of colliding (the failure that made --chart-6 and --chart-8 identical in Nord), and theme-responsive without five more entries in every theme block. Mixed toward --color-surface, not transparent, so low steps stay legible. Browser-verified across mocha/latte/nord/gruvbox-dark/high-contrast-light: all five steps resolve, all five distinct, luminance monotonic in every theme with a 0.08-0.12 minimum step. Direction inverts between dark and light themes, which is correct — the ramp runs surface -> accent. The heatmap legend now mirrors getCellStyle's bands exactly; it previously drew a fourth swatch (teal) that no cell used in themes where teal and sapphire coincide. Six guards added, each verified to fail against its regression. Also: importing SettingsContext into HopDistributionWidget broke that widget's test suite at collection time — the real context pulls in `initReactI18next`, which the file's partial react-i18next mock does not provide. Mocked `useSettings` there instead of widening the i18n mock; the test has no interest in settings beyond the gradient. Caught only because the JSON reporter reports `success:false` with `failed:0` for a suite-level failure. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EtJnjbUgYwJfNU6XXACbFf
|
Claude finished @Yeraze's task —— View job PR Review: feat(themes): add a sequential scale; fix the magnitude ramps (Phase 2a)Tasks:
Overall this is a well-reasoned, cleanly executed change. The framing in the PR description (three distinct color semantics: role / categorical / sequential) is exactly right and the implementation follows through. A few observations: Bug: Wrong import path for
|
Summary
Folds in the widget-ramp bug, as asked. Investigating it corrected my own framing of it: only one of the three widgets is a hop ramp.
HopDistributionWidgetgetHopColor(hop, overlayColors.hopColors)DistanceDistributionWidget--seq-NHopDistanceHeatmapWidget--seq-NThe hop one was a genuine bug: its private list disagreed with the map — 2 hops rendered blue there and teal here — and silently ignored
overlayColors.hopColors, the gradient the user can configure and the map honours.The other two are magnitude, not hops. Pointing them at
hopColorswould have mislabelled distance buckets as hop counts. Pointing them at--chart-Nwould have repeated the exact category error Phase 1 fixed.The third kind of colour
A role says what a colour means. A categorical slot only has to differ from its neighbours. A sequential step has to read as ordered — step 4 must look like "more" than step 2. Categorical hues cannot do that job, which is why both ramps reached past the role layer into raw
--ctp-*for hues no role provided.--seq-1..5are built withcolor-mixfrom the accent rather than picked from the palette, which buys three things the palette can't:--chart-6and--chart-8render identically in Nord is structurally impossible hereMixed toward
--color-surfacerather thantransparent, so low steps stay legible instead of dissolving into the background.Browser-verified, not assumed
Across mocha / latte / nord / gruvbox-dark / high-contrast-light:
Luminance direction inverts between dark and light themes, which is correct — the ramp runs surface → accent.
Also fixed: the heatmap legend drew a fourth swatch (teal) that no cell used in themes where teal and sapphire coincide. It now mirrors
getCellStyle's bands exactly.A collection-time break worth naming
Importing
SettingsContextintoHopDistributionWidgetbroke that widget's test suite — the real context pulls ininitReactI18next, which the file's partialreact-i18nextmock doesn't provide. MockeduseSettingsthere instead of widening the i18n mock, since the test has no interest in settings beyond the gradient.It only surfaced because the JSON reporter reported
success: falsewithfailed: 0— a suite-level collection failure with zero failing assertions. The pass/fail test count alone would have looked clean.Test plan
npx tsc --noEmit— 0 errorsnpm run lint:ci— cleannpx vitest run: success=true, 13,693 passed, 0 failed, 0 failed suites--chart-N, magnitude widgets use--seq-and no raw palette, hop widget routes through the shared scale--ctp-teal; exactly the two intended tests failed)--seq-*present in the served bundle before browser-measuringScope
Phase 2a. The bulk
--ctp-*migration (62 occurrences, 20 files) and the never-defined--ctp-*-rgboverlays follow in 2b — kept separate because this one is behavioural and that one is mechanical.Generated by Claude Code
https://claude.ai/code/session_01EtJnjbUgYwJfNU6XXACbFf