Skip to content

fix(chat): theme mermaid diagrams to the active palette and re-render on theme change#5587

Open
BrunooMoniz wants to merge 1 commit into
odysseus-dev:devfrom
BrunooMoniz:fix/mermaid-theming
Open

fix(chat): theme mermaid diagrams to the active palette and re-render on theme change#5587
BrunooMoniz wants to merge 1 commit into
odysseus-dev:devfrom
BrunooMoniz:fix/mermaid-theming

Conversation

@BrunooMoniz

Copy link
Copy Markdown
Contributor

Summary

Mermaid diagrams were always drawn with Mermaid's built-in dark theme: initMermaid() in static/js/markdown.js called mermaid.initialize({ startOnLoad: false, theme: 'dark', securityLevel: 'loose' }) exactly once (guarded by window.__odysseusMermaidReady). Because Mermaid bakes colours into the SVG at render time, a diagram never followed the app's CSS variables — on any light theme it was dark-filled with light text on a light page — and switching themes at runtime left already-rendered diagrams untouched. This PR drives Mermaid's themeable base theme from the app's existing theme tokens instead: initMermaid() now builds themeVariables from the live CSS variables (--bg, --panel, --fg, --border, --accent / --red, --font-family) so node fills, borders, edges, text, and font all track the active palette, and it re-initialises whenever that palette changes. renderMermaid() records each diagram's source before Mermaid overwrites the <pre> with an SVG, and theme.js dispatches an odysseus-theme-changed event from applyColors() that a small debounced listener uses to re-render every on-screen diagram with the new palette. It stays on the CDN-loaded Mermaid, keeps securityLevel: 'loose', and introduces no new colours, fonts, or components — only the theming and the re-render-on-switch.

Target branch

  • This PR targets dev, not main. All PRs land in dev; main is curated by the maintainer at each release. If your PR is on main by accident, click "Edit" on this PR and change the base.

Linked Issue

Fixes #5586

Type of Change

  • Bug fix (non-breaking — fixes a confirmed issue)
  • New feature (non-breaking — adds new behaviour)
  • Breaking change (changes or removes existing behaviour)
  • Refactor / cleanup (behaviour unchanged)
  • Documentation only
  • CI / tooling / configuration

Checklist

  • I searched open issues and open PRs — this is not a duplicate.
  • This PR targets dev
  • My changes are limited to the scope described above — no unrelated refactors or whitespace changes mixed in.
  • I actually ran the app (docker compose up or uvicorn app:app) and verified the change works end-to-end. Type-checks and unit tests are not enough.

How to Test

Steps a reviewer can reproduce (full app):

  1. docker compose up -d --build, open the chat.
  2. Get the assistant to reply with a Mermaid diagram, e.g. prompt it to echo exactly:
    ```mermaid
    flowchart TD
      Start([Start]) --> Process[Process]
      Process --> Decision{Decision}
      Decision -->|Yes| End([End])
      Decision -->|No| Process
    ```
    
  3. On current dev: the diagram renders with Mermaid's dark theme no matter which app theme is active — on a light preset it is dark-on-light and clashes, and switching themes afterwards does not retheme it. With this branch: the diagram uses the active palette. Open the theme picker, switch between a dark preset and a light one (for example darklight / paper), and the on-screen diagram re-renders to match each time.

What was verified for this change:

  • Rendered through the patched theming (Mermaid theme: 'base' + themeVariables built from the app's CSS variables) in Chromium (desktop, 1280px) and WebKit (mobile, iPhone 12, 390px), for the built-in dark and light presets — see the screenshots below.
  • node --check static/js/markdown.js and node --check static/js/theme.js — pass.
  • python -m pytest tests/test_mermaid_theming_js.py — 2 passed (palette → themeVariables mapping for light vs dark; an odysseus-theme-changed dispatch re-initialises Mermaid with the new palette and re-renders the diagram from its saved source).
  • python -m pytest tests/test_markdown_rendering_js.py — 13 passed (no regression in the renderer this touches).
  • Full python -m pytest — 4618 passed, 5 skipped; the only 2 failures (tests/test_research_report_read.py) reproduce identically on unmodified dev and are unrelated to this change.

Files changed:

  • static/js/markdown.jsinitMermaid() builds Mermaid's base theme from the app's CSS variables (theme: 'base' + themeVariables) instead of a hard-coded theme: 'dark', and re-initialises when the palette signature changes; renderMermaid() captures each diagram's source before Mermaid replaces it with an SVG; a debounced odysseus-theme-changed listener re-renders on-screen diagrams with the new palette. Adds a small exported _mermaidThemeVariables(palette) used by the tests.
  • static/js/theme.jsapplyColors() dispatches an odysseus-theme-changed CustomEvent so theme-reactive renderers (Mermaid) can follow a palette change. No colour or behaviour change to the theme system itself.
  • tests/test_mermaid_theming_js.py — node-driven tests (palette → themeVariables mapping for light and dark; a theme-change dispatch triggers re-initialise + re-render), following the existing tests/test_markdown_rendering_js.py convention.

Visual / UI changes — REQUIRED if you touched anything that renders

Anything that changes what the UI looks like — buttons, icons, padding, colors, fonts, spacing, layout, CSS, HTML, SVG, or any static/js/ module that draws to the DOM — needs all of the following.

  • Screenshot or short clip of the change in the running app, attached below. Mobile screenshot too if the change affects mobile.
    • How the screenshots were captured: rendered through the patched theming — Mermaid theme: 'base' with themeVariables produced by the module's own _mermaidThemeVariables() from the app's CSS variables — in Chromium (desktop, 1280px) and WebKit (mobile, iPhone 12, 390px), using the built-in dark and light theme presets.
  • Style match: the change uses Odysseus's existing visual language. Specifically:
    • Reuse existing CSS variables (--red, --fg, --bg, --card, --border, etc.) — do not introduce new color values, font sizes, or spacing units. (This change reads the existing --bg/--panel/--fg/--border/--accent/--red/--font-family variables to theme the diagram; it adds none.)
    • Reuse existing button/input/card/border classes. Don't invent parallel styling.
    • No Unicode emoji in UI or code. Use inline SVG (matching the monochrome icon style already in static/index.html) or plain text.
    • Monospaced font (Fira Code) for primary UI text. Don't override.
    • Dark theme is the default; any light-mode work must be wired through the existing theme system, not hard-coded.
  • No new component patterns. If a similar widget already exists in the app, extend it instead of writing a parallel one.
  • I am not an LLM agent submitting a bulk PR. If you are, please open an issue describing the problem first — bulk auto-generated PRs that don't match the project's visual style are closed on sight, even when the underlying fix is correct.

Screenshots / clips

Desktop — dark theme

mermaid dark, desktop

Desktop — light theme

mermaid light, desktop

Mobile — dark theme

mermaid dark, mobile

Mobile — light theme

mermaid light, mobile

… on theme change

initMermaid() initialised Mermaid once with a hard-coded theme: 'dark', so
diagrams never followed the app palette (dark-on-light on light themes) and
did not retheme on a theme switch. Build Mermaid's themeable 'base' theme from
the app's existing CSS variables (--bg/--panel/--fg/--border/--accent|--red/
--font-family), re-initialise when the palette changes, and re-render on-screen
diagrams when theme.js dispatches an odysseus-theme-changed event. Stays on the
CDN-loaded Mermaid; no new colours, fonts, or components.
@github-actions github-actions Bot added the ready for review Description complete — ready for maintainer review label Jul 18, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ready for review Description complete — ready for maintainer review

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Mermaid diagrams keep a fixed dark theme and don't follow the active palette

1 participant