Skip to content

fix(gantt): readable done-task text in dark theme#7432

Merged
knsv merged 2 commits into
developfrom
bug/5979_gantt_dark_mode_done_text
Mar 2, 2026
Merged

fix(gantt): readable done-task text in dark theme#7432
knsv merged 2 commits into
developfrom
bug/5979_gantt_dark_mode_done_text

Conversation

@knsv

@knsv knsv commented Mar 2, 2026

Copy link
Copy Markdown
Collaborator

Summary

Resolves #5979

  • In the dark theme, taskTextDarkColor was derived from darkTextColor — a light color (~86% lightness) meant for use against the dark diagram background. When applied to done-task text over doneTaskBkgColor (lightgrey), this produced unreadable light-on-light text.
  • Changed taskTextDarkColor to invert(this.doneTaskBkgColor) so the text color is derived from the background it sits on, staying contrast-aware within the theme pipeline. If a user overrides doneTaskBkgColor via themeVariables, the text color adjusts automatically.

Classification

  • Change type: theme / style (dark theme only)
  • Breaking change: No — fixes broken contrast; the current behaviour is a bug
  • Shared code touched: No — only theme-dark.js

Verification

  • TDD: test failed before fix (taskTextDarkColor === darkTextColor, light), passes after (taskTextDarkColor === #2c2c2c, dark)
  • Lint: passed
  • Unit tests: passed (pnpm vitest run packages/mermaid/src/themes/)
  • Programmatic contrast check: #2c2c2c on lightgrey — high contrast confirmed
  • Visual spot-check: Playwright not available in worktree — programmatic verification only
  • Full e2e: not run locally — e2e snapshot test added for CI
  • Changeset: generated (patch)

🤖 Generated with Claude Code

In the dark theme, taskTextDarkColor was set to darkTextColor — a light
color (~hsl 86% lightness) intended for the dark background. When applied
to done-task text over doneTaskBkgColor (lightgrey), this produced
unreadable light-on-light text.

Derive taskTextDarkColor via invert(doneTaskBkgColor) so it stays
contrast-aware within the theme pipeline. If a user overrides
doneTaskBkgColor through themeVariables, text color adjusts automatically.

Resolves #5979

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@changeset-bot

changeset-bot Bot commented Mar 2, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 4cd3fff

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
mermaid Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@netlify

netlify Bot commented Mar 2, 2026

Copy link
Copy Markdown

Deploy Preview for mermaid-js ready!

Name Link
🔨 Latest commit 4cd3fff
🔍 Latest deploy log https://app.netlify.com/projects/mermaid-js/deploys/69a5717d0cfa1e0007c1f65f
😎 Deploy Preview https://deploy-preview-7432--mermaid-js.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@github-actions github-actions Bot added the Type: Bug / Error Something isn't working or is incorrect label Mar 2, 2026
@pkg-pr-new

pkg-pr-new Bot commented Mar 2, 2026

Copy link
Copy Markdown

Open in StackBlitz

@mermaid-js/examples

npm i https://pkg.pr.new/@mermaid-js/examples@7432

mermaid

npm i https://pkg.pr.new/mermaid@7432

@mermaid-js/layout-elk

npm i https://pkg.pr.new/@mermaid-js/layout-elk@7432

@mermaid-js/layout-tidy-tree

npm i https://pkg.pr.new/@mermaid-js/layout-tidy-tree@7432

@mermaid-js/mermaid-zenuml

npm i https://pkg.pr.new/@mermaid-js/mermaid-zenuml@7432

@mermaid-js/parser

npm i https://pkg.pr.new/@mermaid-js/parser@7432

@mermaid-js/tiny

npm i https://pkg.pr.new/@mermaid-js/tiny@7432

commit: 2adebfe

@codecov

codecov Bot commented Mar 2, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 0% with 3 lines in your changes missing coverage. Please review.
✅ Project coverage is 3.54%. Comparing base (3b5f67d) to head (4cd3fff).
⚠️ Report is 12 commits behind head on develop.

Files with missing lines Patch % Lines
packages/mermaid/src/themes/theme-dark.js 0.00% 3 Missing ⚠️
Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##           develop   #7432      +/-   ##
==========================================
- Coverage     3.55%   3.54%   -0.02%     
==========================================
  Files          489     490       +1     
  Lines        48774   48938     +164     
  Branches       765     766       +1     
==========================================
  Hits          1734    1734              
- Misses       47040   47204     +164     
Flag Coverage Δ
unit 3.54% <0.00%> (-0.02%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
packages/mermaid/src/themes/theme-dark.js 2.23% <0.00%> (ø)

... and 1 file with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@argos-ci

argos-ci Bot commented Mar 2, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Argos notifications ↗︎

Build Status Details Updated (UTC)
default (Inspect) 👍 Changes approved 2 changed, 2 added Mar 2, 2026, 11:28 AM

@ashishjain0512 ashishjain0512 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[sisyphus-bot]

Review — PR #7432: fix(gantt): readable done-task text in dark theme

Thanks @knsv — excellent root-cause analysis and a clean fix for a long-standing readability issue. The PR description is thorough and the TDD approach is spot on.


What's working well

🎉 [praise] The root-cause analysis in the PR description is exemplary — tracing taskTextDarkColor → darkTextColor → lighten(invert('#323D47'), 10) to show why the color ends up light is exactly the level of detail that makes theme bugs debuggable later.

🎉 [praise] Using invert(this.doneTaskBkgColor) instead of a hardcoded color keeps the fix within the theme pipeline — if a user overrides doneTaskBkgColor via themeVariables, the text color adapts automatically. This is the right pattern.

🎉 [praise] Both a unit test and an e2e visual regression test are included. The e2e test covers multiple gantt task states (done, active, future, crit+done) which gives good regression coverage.


Things to address

🟡 [important] Pie chart regression via taskTextDarkColor fallback — theme-dark.js:233,237

taskTextDarkColor is used as the fallback for pieTitleTextColor and pieLegendTextColor:

this.pieTitleTextColor = this.pieTitleTextColor || this.taskTextDarkColor;  // line 233
this.pieLegendTextColor = this.pieLegendTextColor || this.taskTextDarkColor;  // line 237

Before this fix, taskTextDarkColor was a light color (darkTextColor ≈ lightened #CDC2B8), which reads well against the dark theme background (#333). After the fix, it becomes invert('lightgrey')#2C2C2C, which is dark-on-dark against the diagram background — likely unreadable pie chart titles and legends.

A straightforward fix would be to set these explicitly before the fallback takes effect, e.g. adding to updateColors() before the pie section:

this.pieTitleTextColor = this.pieTitleTextColor || this.mainContrastColor;
this.pieLegendTextColor = this.pieLegendTextColor || this.mainContrastColor;

mainContrastColor is 'lightgrey' in dark theme, which reads well on #333. This decouples pie text from the gantt-specific variable. It would be great to add a pie chart dark-theme e2e test alongside the gantt one to verify.


🟢 [nit] Unit test assertion strength — theme-dark.spec.js:20

The test asserts expect(color).not.toBe(theme.darkTextColor) which is a negative assertion — it confirms the bug is gone but doesn't verify the fix is correct. A positive assertion checking the computed value is a recognizably dark color (e.g., checking the hex value or using a simple lightness heuristic) would catch future regressions more precisely.


Summary: The fix direction is correct and well-reasoned. The one item to address is the downstream impact on pie chart colors in dark theme — once that's handled, this should be good to go. Let's get this across the finish line! 🚀

@knsv knsv marked this pull request as ready for review March 2, 2026 10:57
…heme

Address PR review: pieTitleTextColor and pieLegendTextColor previously
fell back to taskTextDarkColor, which is now a dark color (#2c2c2c).
This would produce unreadable dark-on-dark text for pie charts.

Decouple by falling back to mainContrastColor (lightgrey) instead,
which reads well on the dark background (#333).

Also strengthen unit test with positive assertion on computed hex value
and add pie chart dark-mode e2e test for regression coverage.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

@ashishjain0512 ashishjain0512 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[sisyphus-bot]

Re-review — PR #7432 (Round 2)

Both items from round 1 are fully addressed in commit 4cd3fff:

🎉 [praise] The pie chart decoupling is clean — pieTitleTextColor and pieLegendTextColor now fall back to mainContrastColor ('lightgrey') instead of taskTextDarkColor, breaking the cross-diagram coupling that would have caused dark-on-dark text. Exactly the right fix.

🎉 [praise] The test coverage is now thorough — positive assertion on the computed hex value ('#2c2c2c'), separate pie chart unit tests confirming 'lightgrey', and a new dark-mode pie e2e snapshot test. This covers both the fix and the regression guard.

Previous items — resolved:

  • 🟡 Pie chart regression — Fixed by decoupling to mainContrastColor
  • 🟢 Unit test assertion strength — Now uses positive toBe('#2c2c2c') assertion

No remaining issues. LGTM — nice work @knsv! 🚀

@knsv knsv added this pull request to the merge queue Mar 2, 2026
Merged via the queue into develop with commit 9670f3d Mar 2, 2026
25 checks passed
@knsv knsv deleted the bug/5979_gantt_dark_mode_done_text branch March 2, 2026 12:08
@github-actions github-actions Bot mentioned this pull request Mar 3, 2026
@knsv

knsv commented Mar 6, 2026

Copy link
Copy Markdown
Collaborator Author

A regression issue was found while testing:
5979_before_after_fix_from_7432

Please note that sometimes when the label does not fit inside the rectangle, the text is displayed next to the graphical bar. After the change in this PR, #7432, it renders with black text in dark mode which is unreadable.

knsv-bot pushed a commit that referenced this pull request Mar 6, 2026
…k mode

When a Gantt done-task label is too wide to fit inside the bar, the renderer
places the text outside (next to the bar) with class `taskTextOutsideLeft` or
`taskTextOutsideRight` plus `doneText{N}`. The `.doneText{N}` rule uses
`taskTextDarkColor !important`, which PR #7432 changed to a dark color
(inverted from lightgrey) for contrast inside the bar. That `!important` also
overrides the lighter `taskTextOutsideColor` that `.taskTextOutside{N}` sets,
making outside-label text black/dark on the dark diagram background.

Fix: add combined-class selectors (`.doneText{N}.taskTextOutsideLeft/Right`)
after the `.doneText{N}` block, using `taskTextOutsideColor !important`. The
combined selectors have higher specificity and appear later in the cascade, so
they win over the single-class rule. Same fix applied to `.doneCritText{N}`.

Fixes regression from PR #7432 (fix for #5979).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
ashishjain0512 pushed a commit that referenced this pull request Mar 6, 2026
…#7456)

* fix(gantt): restore readable outside-text color for done tasks in dark mode

When a Gantt done-task label is too wide to fit inside the bar, the renderer
places the text outside (next to the bar) with class `taskTextOutsideLeft` or
`taskTextOutsideRight` plus `doneText{N}`. The `.doneText{N}` rule uses
`taskTextDarkColor !important`, which PR #7432 changed to a dark color
(inverted from lightgrey) for contrast inside the bar. That `!important` also
overrides the lighter `taskTextOutsideColor` that `.taskTextOutside{N}` sets,
making outside-label text black/dark on the dark diagram background.

Fix: add combined-class selectors (`.doneText{N}.taskTextOutsideLeft/Right`)
after the `.doneText{N}` block, using `taskTextOutsideColor !important`. The
combined selectors have higher specificity and appear later in the cascade, so
they win over the single-class rule. Same fix applied to `.doneCritText{N}`.

Fixes regression from PR #7432 (fix for #5979).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* test(gantt): add e2e snapshot for done-task outside-text in dark mode

Covers the regression from #7433 where done-task labels displayed outside
the bar (text too wide for the bar width) rendered in unreadable dark color
in dark theme.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* test(gantt): add separate inside/outside e2e snapshots for dark mode done tasks

Split the dark mode done-task coverage into two explicit tests:
- inside-text: label fits within the bar (long bar, short label)
- outside-text: label overflows the bar (short bar, long label) — regression case for #7433

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: knsv-bot <knsv-bot@macos.shared>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
@github-actions github-actions Bot mentioned this pull request Mar 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Type: Bug / Error Something isn't working or is incorrect

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Gantt Chart "done" Tasks are not readable in dark mode

2 participants