Skip to content

feat(site): dark mode (persisted toggle + theme-aware chart) - #216

Open
jessie1111101 wants to merge 2 commits into
feat/scoring-v1-frontendfrom
feat/site-dark-mode
Open

feat(site): dark mode (persisted toggle + theme-aware chart)#216
jessie1111101 wants to merge 2 commits into
feat/scoring-v1-frontendfrom
feat/site-dark-mode

Conversation

@jessie1111101

@jessie1111101 jessie1111101 commented Jul 20, 2026

Copy link
Copy Markdown
Collaborator

Summary

Adds a light/dark theme toggle to the leaderboard site — its own PR, kept out of the scoring work.

Stacked on #206 (it themes the Phase 1 UI, incl. the new metric toggle + catastrophic badge). Retarget to main once #206 lands.

What's here

  • Theming infra: Tailwind darkMode: "class"; a small theme util (lib/theme.js) that resolves saved choice → OS prefers-color-scheme, persists to localStorage, and is applied pre-paint in main.jsx (no light flash); a persisted ThemeToggle (sun/moon) in the app shell.
  • dark: variants across every surface: page shell, cards, headers, rows (incl. the ⚠ badge), filter bar, metric toggle, chips, identity block, states, detail page, and dark scrollbars/body.
  • Theme-aware chart: Chart.js can't use dark:, so a useIsDark hook (MutationObserver on the <html> class) drives the trend chart's grid/tick/legend colors — it restyles live when you toggle, no refresh.

Test plan

  • npm run test95/95; npm run build:staging — clean.
  • Preview locally (toggle top-right; refresh persists the choice; chart recolors live).

@jessie1111101
jessie1111101 force-pushed the feat/scoring-v1-frontend branch from 3a21b8f to 36d9d60 Compare July 22, 2026 18:28
Comment thread site/src/index.css
border-radius: 3px;
}

.dark ::-webkit-scrollbar-track {

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.

Have you considered adding dark color-scheme and standard scrollbar-color rules to ".dark / .dark body" instead so that this works in general and not just for WebKit/Blink browsers

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Good call, Firefox was getting light scrollbars in dark mode. Added color-scheme on :root/.dark, which also covers browser UI that dark: can't reach (form controls, spellcheck underlines), plus standard scrollbar-color/scrollbar-width. Kept -webkit-* for older Chrome/Safari, which ignore those and are the only engines that can size the bar this precisely.

@@ -0,0 +1,40 @@
// Light/dark theme toggle. Persists the choice (localStorage) and flips the

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.

nit: Not a blocker for this but we could add an event listener to kepp multiple tabs synchronized instantly when toggling themes.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Took it, it was small. Now listens for storage (fires only in other tabs) so they follow a toggle immediately; a cleared key falls back to the default. Exported THEME_KEY so the listener and writer can't drift.

@jessie1111101
jessie1111101 force-pushed the feat/scoring-v1-frontend branch from e181244 to be980f6 Compare July 28, 2026 17:08
@jessie1111101
jessie1111101 force-pushed the feat/scoring-v1-frontend branch from be980f6 to a581796 Compare July 31, 2026 22:14
- tailwind darkMode:'class'; theme util (localStorage + prefers-color-scheme),
  applied pre-paint in main.jsx (no flash); a persisted ThemeToggle in the App
  shell.
- dark: variants across every surface (cards, headers, rows, filter bar, metric
  toggle, chips, identity, states, detail) + dark scrollbars/body.
- TrendChart: a useIsDark hook (MutationObserver on the <html> class) drives the
  Chart.js grid/tick/legend colors so the canvas restyles live on toggle.

vitest 95/95; build clean.
Review follow-ups (Simran):
- Dark scrollbars were WebKit-only. Set color-scheme on :root/.dark so the
  browser renders its own UI for the active theme in every engine, and add the
  standard scrollbar-color/scrollbar-width alongside the -webkit-* rules.
- ThemeToggle listens for the storage event so open tabs follow a toggle
  immediately instead of drifting until reload.
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.

2 participants