Skip to content

feat(dash): dark mode for the web dashboard - #888

Merged
iamtoruk merged 1 commit into
getagentseal:mainfrom
ozymandiashh:feat/854-dash-dark-mode
Aug 3, 2026
Merged

feat(dash): dark mode for the web dashboard#888
iamtoruk merged 1 commit into
getagentseal:mainfrom
ozymandiashh:feat/854-dash-dark-mode

Conversation

@ozymandiashh

@ozymandiashh ozymandiashh commented Aug 3, 2026

Copy link
Copy Markdown
Collaborator

Closes #854

Implements exactly the shape proposed in my comment on the issue and signed off by @iamtoruk: the .dark token block reusing the Electron palette, the pre-paint bootstrap with prefers-color-scheme fallback where the toggle overrides and wins, the header sun/moon toggle persisted to localStorage, and the stray hex values folded into tokens. Contained to dash/, no new dependencies, per the approval.

What it does

Dark mode for the web dashboard (codeburn web), reusing the groundwork that was already half-laid:

  • dash/src/index.css: a .dark { ... } block overriding the same token set as :root, plus color-scheme: dark. Values are lifted from the dark palette the repo already ships for the Electron surface (app/renderer/styles/plain.css: #0e1013 canvas, #16181d panel, #e8eaee ink, #282c33 line, ok/warn/bad accents), so the two surfaces stay visually consistent. The previously dead @custom-variant dark declaration now has something to bind to. Chart colors (--chart-1..10) are re-derived for dark-background contrast. No :root token was removed or renamed; light mode renders byte-identically.
  • dash/index.html: a tiny inline script ahead of the bundle applies .dark from localStorage['codeburn-theme'], falling back to prefers-color-scheme, so there is no flash of light theme. localStorage access is wrapped in try/catch: in storage-disabled contexts (some embeds/webviews) the script degrades to the media query instead of dying before the class is applied.
  • Toggle in the header (sun/moon, matching the existing icon style), persisting to the same key. When no explicit preference is stored, a matchMedia('change') listener follows live OS theme flips.
  • Stray colors: the few hardcoded hex values in components now go through tokens (text-brand, accent-primary, bg-chart-5, text-chart-8), and CHART_COLORS uses var(--chart-N) so Recharts follows the active theme. An adversarial review pass also caught non-hex literals a grep for #RRGGBB cannot see: the bar-chart hover cursor was rgba(0,0,0,0.04) (invisible on #0e1013) and is now a themed --chart-hover-cursor token with light and dark values.

Not changed

No new dependencies. No dash/package.json, Vite or Tailwind config changes. Nothing outside dash/.

Verification

  • cd dash && npm run build clean; npx tsc --noEmit clean.
  • grep -RInE '#[0-9a-fA-F]{3,8}\b' dash/src --include='*.tsx' --include='*.ts' returns zero lines outside index.css.
  • Token parity audited: every :root color token has a .dark override; light-mode values unchanged.
  • Reviewed independently by four models (Gemini 3.1 Pro, GLM 5.2, Kimi, GPT-5.6); all findings (hover cursor, unguarded localStorage, missing OS-change listener) were fixed and re-verified.

One honest limitation: the build and type gates cannot verify runtime SVG painting, so the var(--chart-N) values in Recharts fills rest on the same mechanism the file already used for var(--color-chart-grid-stroke) on CartesianGrid, which renders correctly today.

@ozymandiashh

Copy link
Copy Markdown
Collaborator Author

@iamtoruk ready for your look whenever suits: implemented exactly the shape you signed off in #854 (token block reusing the Electron palette, color-scheme, pre-paint bootstrap, localStorage toggle with OS default, stray hexes folded into tokens, contained to dash/, zero new deps). CI is green; appx did not run because the diff never leaves dash/. One interplay note: my review on #783 checked its two new panels against this token block, and they restyle correctly, so merge order between the two does not matter visually.

@iamtoruk iamtoruk left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Reviewed on the merged tree; implements exactly the shape signed off on #854.

  • Light mode is byte-identical: the change is purely additive, no :root token removed or renamed. Token parity confirmed (every :root color token has a .dark override; only --radius, a non-color, is untouched).
  • Dark values reuse the Electron surface palette, so the web dashboard and the app stay consistent. Charts re-derived for dark contrast, and the invisible rgba hover cursor is now a themed token.
  • Pre-paint bootstrap applies the theme before first paint (no flash), degrades to the OS media query when storage is disabled. The toggle initializes from that class, persists to the same key, and follows live OS theme flips only while no explicit choice is stored. Accessible (aria-label/title).
  • dash build and tsc clean; contained to dash/, no new dependencies.

Good to merge.

@iamtoruk
iamtoruk merged commit 4c04212 into getagentseal:main Aug 3, 2026
3 checks passed
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.

Feature request: dark mode for the web dashboard (codeburn web)

2 participants