Skip to content

fix(charts): dark-mode readability audit — pie labels, radar, choropleth, map controls, graph edges (#1154) - #1177

Merged
alfredo1996 merged 1 commit into
release/1.3from
fix/issue-1154-darkmode-audit
Jul 4, 2026
Merged

fix(charts): dark-mode readability audit — pie labels, radar, choropleth, map controls, graph edges (#1154)#1177
alfredo1996 merged 1 commit into
release/1.3from
fix/issue-1154-darkmode-audit

Conversation

@alfredo1996

@alfredo1996 alfredo1996 commented Jul 4, 2026

Copy link
Copy Markdown
Owner

Closes #1154 (the bar-label part landed in #1167; this completes the audit).

Method

Screenshot sweep of all 92 chart stories × 2 themes via Storybook + Playwright, reviewed by three parallel readers, each finding root-caused in code and re-verified with after screenshots.

Fixes (each verified before/after)

Finding Root cause Fix
Pie slice labels black-on-dark ECharts default label (pixel-confirmed #333 + white halo) theme pie.label → foreground, no halo (same as the bar fix)
Radar indicator labels dim radar.axisName doesn't inherit textStyle explicit muted-fg per theme
Choropleth visualMap legend dim visualMap.textStyle doesn't inherit either explicit muted-fg per theme
Choropleth region labels invisible in dark default dark text on near-black regions white-with-shadow (treemap pattern) in dark mode only — an unconditional version washed out the light map; caught in verification and made theme-conditional
Map attribution: white strip + amber links in dark our .dark override tied Leaflet's .leaflet-container .leaflet-control-attribution on specificity and lost on load order (leaflet.css imported lazily) selector now includes .leaflet-container; also styled the glaring disabled zoom button
Graph edges near-invisible in dark NVL default relationship grey on near-black canvas explicit mid-grey default in dark; explicit edge colors normalized hsl→hex (same NVL constraint as #1157)

Deliberately left as minors (noted on the issue)

Sankey ribbon tint, gauge low-value track, line-chart axis-name/legend overlap (both themes — layout, not contrast), map marker translucency over dark tiles, circle-packing label occlusion.

Tests

  • theme-defaults: pie label fg/no-halo, radar axisName, visualMap text — both themes (6 new).
  • graph-chart: dark edge default + hsl→hex normalization (2 new).
  • Component suite 1894 green; theme + charts E2E pass (2 unrelated login-timeout flakes, pass in CI).

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Bug Fixes
    • Improved chart and map readability in dark mode, including clearer labels, legend text, and disabled controls.
    • Graph relationship lines now use a consistent fallback color in dark mode and correctly display custom edge colors.
    • Pie, radar, and visual map text styling now stays legible across themes.
    • Updated Leaflet dark-mode styling for attribution and disabled zoom controls.

…eth, map controls, graph edges (#1154)

Storybook screenshot sweep of all 92 chart stories in both themes
surfaced the remaining dark-mode readability failures after the bar-label
fix (#1167). Fixed, each verified before/after:

- Pie slice labels: ECharts' default dark-fill + light-halo label style
  (pixel-confirmed #333 with white stroke) was black-on-dark. Theme-level
  `pie.label` → foreground, no halo — same fix as bar.
- Radar indicator labels + visualMap legend text: neither inherits the
  global textStyle; their dim defaults were hard to read on the dark
  canvas. Explicit muted-foreground per theme.
- Choropleth region labels: invisible on dark no-data regions. Dark mode
  now uses the treemap white-with-shadow fill-label pattern; light mode
  keeps the default dark text (an unconditional white label washed out on
  the pale light map — caught in verification and made theme-conditional).
- Leaflet attribution: the `.dark` background override tied Leaflet's own
  `.leaflet-container .leaflet-control-attribution` on specificity and
  lost on load order (leaflet.css is imported lazily by map-chart), so
  the strip stayed white with amber links. Selector now includes
  `.leaflet-container` to win outright. Also styled the disabled zoom
  button, whose light-grey Leaflet default glared on the dark stack.
- Graph edges: NVL's default relationship grey nearly vanishes on the
  dark canvas — uncolored edges get an explicit mid-grey in dark mode,
  and explicit edge colors are normalized hsl→hex for NVL (#1157 class).

Known minors deliberately left (noted on #1154): sankey ribbon tint,
gauge low-value track, line-chart axis-name/legend overlap (both themes,
layout), map marker translucency over dark tiles, circle-packing label
occlusion.

Tests: theme-defaults (pie/radar/visualMap, both themes), graph-chart
edge color mapping (dark default + hsl→hex). Component suite 1894 green;
theme + charts E2E pass.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@alfredo1996 alfredo1996 added area:a11y Accessibility area:charts Chart rendering area:design Visual design, tokens, typography bug Something isn't working pkg:component UI component library labels Jul 4, 2026
@coderabbitai

coderabbitai Bot commented Jul 4, 2026

Copy link
Copy Markdown

Review Change Stack

Walkthrough

Dark-mode text and styling readability improvements across chart theming (pie labels, radar axisName, visualMap textStyle), choropleth map labels, graph edge colors, and Leaflet CSS selectors, with accompanying unit tests.

Changes

Dark mode readability fixes

Layer / File(s) Summary
Theme defaults: pie, radar, visualMap label colors
component/src/charts/theme.ts, component/src/charts/__tests__/theme-defaults.test.ts
Pie slice labels use theme foreground color with no text halo; radar axisName and visualMap textStyle now use explicit legend/theme colors in both light and dark themes, validated by new tests.
Choropleth map label fill style
component/src/charts/choropleth-chart.tsx
Imports fillLabelStyle and applies it to label and emphasis.label when dark mode is active.
Graph chart edge color normalization
component/src/charts/graph-chart.tsx, component/src/charts/__tests__/graph-chart.test.tsx
toNvlRelationship accepts a dark flag, normalizes provided edge colors via toNvlColor, and defaults uncolored edges to a mid-grey in dark mode; tests verify both behaviors.
Leaflet dark-mode CSS
component/src/index.css
Attribution dark-mode selectors are scoped for specificity and a new rule styles the disabled zoom button in dark mode.

Estimated code review effort: 2 (Simple) | ~15 minutes

Possibly related PRs

Suggested labels: testing

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title is concise and accurately reflects the main dark-mode readability audit changes in charts and controls.
Linked Issues check ✅ Passed The PR covers the dark-mode readability audit with theme-aware text colors and supporting tests, aligning with issue #1154’s contrast goals.
Out of Scope Changes check ✅ Passed The edits stay within chart dark-mode readability work and related tests, with no clearly unrelated code changes.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/issue-1154-darkmode-audit

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@component/src/charts/__tests__/theme-defaults.test.ts`:
- Around line 92-95: The assertions in theme-defaults.test.ts are passing a
duplicate second argument to Jest’s toBe matcher, which causes a TypeScript
compile error. Update the affected expectations in the axisName and visualMap
tests so each expect(...).toBe(...) call receives only the single intended
value, using the existing theme.legend textStyle color expression once in each
assertion.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 7069edfe-4ce8-4156-a390-3918ba327b82

📥 Commits

Reviewing files that changed from the base of the PR and between d2e58bb and 5b25391.

📒 Files selected for processing (6)
  • component/src/charts/__tests__/graph-chart.test.tsx
  • component/src/charts/__tests__/theme-defaults.test.ts
  • component/src/charts/choropleth-chart.tsx
  • component/src/charts/graph-chart.tsx
  • component/src/charts/theme.ts
  • component/src/index.css

Comment on lines +92 to +95
expect(axisName.color).toBe(
(theme.legend as { textStyle: { color: string } }).textStyle.color,
);
});

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🔴 Critical | ⚡ Quick win

Duplicate argument passed to toBe() — TS compile error.

Both new assertions pass the same expression twice into .toBe(...), e.g.:

expect(axisName.color).toBe(
  (theme.legend as { textStyle: { color: string } }).textStyle.color,
  (theme.legend as { textStyle: { color: string } }).textStyle.color,
);

toBe takes a single argument; TypeScript will reject the extra argument, breaking the build/test run. Same duplication in the visualMap test.

🐛 Proposed fix
       expect(axisName.color).toBe(
-        (theme.legend as { textStyle: { color: string } }).textStyle.color,
         (theme.legend as { textStyle: { color: string } }).textStyle.color,
       );
       expect((vm.textStyle as Record<string, unknown>).color).toBe(
-        (theme.legend as { textStyle: { color: string } }).textStyle.color,
         (theme.legend as { textStyle: { color: string } }).textStyle.color,
       );

Also applies to: 100-103

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@component/src/charts/__tests__/theme-defaults.test.ts` around lines 92 - 95,
The assertions in theme-defaults.test.ts are passing a duplicate second argument
to Jest’s toBe matcher, which causes a TypeScript compile error. Update the
affected expectations in the axisName and visualMap tests so each
expect(...).toBe(...) call receives only the single intended value, using the
existing theme.legend textStyle color expression once in each assertion.

@sonarqubecloud

sonarqubecloud Bot commented Jul 4, 2026

Copy link
Copy Markdown

@alfredo1996
alfredo1996 merged commit d48cd34 into release/1.3 Jul 4, 2026
15 checks passed
@alfredo1996
alfredo1996 deleted the fix/issue-1154-darkmode-audit branch July 4, 2026 17:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:a11y Accessibility area:charts Chart rendering area:design Visual design, tokens, typography bug Something isn't working pkg:component UI component library

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants