Skip to content

Fix: chart scenes unreadable on dark themes - #488

Open
TROY665 wants to merge 2 commits into
calesthio:mainfrom
TROY665:fix/chart-text-color-dark-theme
Open

Fix: chart scenes unreadable on dark themes#488
TROY665 wants to merge 2 commits into
calesthio:mainfrom
TROY665:fix/chart-text-color-dark-theme

Conversation

@TROY665

@TROY665 TROY665 commented Aug 10, 2026

Copy link
Copy Markdown

Fix: chart scenes unreadable on dark themes

Companion to #469 ("keep themed text legible on light playbooks"), which threads
theme colours into the text overlay components (CaptionOverlay, SectionTitle,
StatReveal, HeroTitle). This does the same for the chart components and
ComparisonCard, which #469 explicitly leaves untouched — same root cause
(hardcoded colour defaults that Explainer.tsx never overrides), opposite
direction (near-black defaults invisible on dark themes, rather than near-white
defaults invisible on light ones).

Both touch Explainer.tsx but in different JSX blocks, so whichever lands second
should rebase cleanly.

Problem

Explainer.tsx passes backgroundColor={bgColor} to the chart components but
never passes textColor. All four chart components — BarChart, LineChart,
PieChart and KPIGrid — default textColor to "#1F2937" (near-black).

On any dark theme the chart title, axis scale, category labels and value labels
are therefore drawn dark-on-dark and are invisible. The data renders correctly;
it simply cannot be seen. Bars, gridlines and series colours are unaffected,
which makes the failure look like "the labels aren't being passed" rather than a
colour bug.

ComparisonCard has the mirror-image version of the same problem: it does
receive textColor, but hardcodes cardBackgroundColor = "#F3F4F6". A dark
theme's light text then lands on a light card. Same symptom, opposite cause.

Reproduction

Render any explainer-data composition on the default dark theme with a
bar_chart or comparison scene:

{
  "type": "bar_chart",
  "title": "Neurons (millions)",
  "showValues": true,
  "chartData": [
    { "label": "Octopus", "value": 500 },
    { "label": "Dog", "value": 530 }
  ]
}

Before: bars and gridlines only — no title, no axis scale, no labels, no values.
After: all text visible.

Fix

  • Forward textColor={textColor} to BarChart, LineChart, PieChart and KPIGrid.
  • Pass cardBackgroundColor={cut.cardBackgroundColor || theme.surfaceColor} to
    ComparisonCard so the inner card follows the active theme.
  • Add cardBackgroundColor?: string to the Cut interface, so a scene can still
    force a light card on a dark theme when a design calls for it.

Six lines, one file. No behaviour change on light themes: the components already
default to the same near-black, so forwarding an explicitly light-theme
textColor produces the identical result.

Tests

Adds two contract tests to tests/contracts/test_remotion_video_transition_contract.py,
following the existing source-assertion style in that file:

  • test_chart_scenes_receive_the_theme_text_color — asserts each of the four
    chart components receives textColor={textColor}
  • test_comparison_card_surface_follows_the_theme — asserts ComparisonCard gets
    a themed cardBackgroundColor

Both fail against the pre-fix Explainer.tsx and pass after it, verified by
stashing the change and re-running.

Verification

Rendered a 7-scene explainer (hero_title, text_card, stat_card, bar_chart,
comparison, callout) on the default dark theme, before and after. Before, the
bar chart showed bars and gridlines only and the comparison card's labels were
invisible. After, the chart shows its title, y-axis scale (0–530), category
labels and per-bar values, and the comparison card shows both labels on a themed
surface. The other five scenes are pixel-identical.

npx tsc --noEmit passes.

…on card

Chart scenes are unreadable on any dark theme. BarChart, LineChart,
PieChart and KPIGrid all default `textColor` to #1F2937 (near-black),
but Explainer only ever passed them `backgroundColor` - so on a dark
theme every title, axis label, category label and value renders
dark-on-dark.

ComparisonCard has the mirror-image bug: it *does* receive the theme's
`textColor`, but hardcodes `cardBackgroundColor = "#F3F4F6"`, painting
light text onto a light card.

Forward `textColor` to the four chart components, and give
ComparisonCard `cut.cardBackgroundColor || theme.surfaceColor` so its
surface follows the theme. Adds `cardBackgroundColor?: string` to the
Cut interface for a per-cut override.

Verified by re-rendering a 7-scene explainer on a dark theme: chart
title, y-axis scale, category labels and per-bar values are all legible,
and the comparison card labels now show on a themed surface.
Follows the existing source-assertion style in this file. Both tests fail
against the pre-fix Explainer and pass after it:

- charts must receive textColor={textColor}, or their labels render
  dark-on-dark (the components default textColor to #1F2937)
- ComparisonCard must get a themed cardBackgroundColor, or its labels
  render light-on-light (the component hardcodes #F3F4F6)
@TROY665
TROY665 requested a review from calesthio as a code owner August 10, 2026 08:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant