Skip to content

feat: add dark / system theme toggle#14

Open
cat-ph wants to merge 5 commits into
Twixes:mainfrom
cat-ph:dark-mode-toggle
Open

feat: add dark / system theme toggle#14
cat-ph wants to merge 5 commits into
Twixes:mainfrom
cat-ph:dark-mode-toggle

Conversation

@cat-ph

@cat-ph cat-ph commented Jun 29, 2026

Copy link
Copy Markdown

What

Adds a three-way Light / System / Dark theme toggle, defaulting to the visitor's OS preference.

  • ThemeProvider (next-themes, class strategy) wired into the root layout; no-flash via its pre-paint script + suppressHydrationWarning on <html>.
  • ThemeToggle (Light / System / Dark) in the app top bar and the marketing footer.
  • A dark palette defined as CSS variables under .dark (P3 + sRGB fallback). Because the UI is already variable-driven, the whole surface flips with almost no per-component changes.
  • Dark highlight.js syntax tokens, and dark: variants for the few hardcoded status colors (diff views, error box).
  • The CodeMirror editor and Mermaid diagrams are made theme-aware.

Notes

  • The grayscale is inverted by role, not by name — --gray-5 stays the "barely off the background" tint, --gray-90 the strongest text — so existing class usage keeps its meaning.
  • error.tsx / MermaidDiagram.tsx carried pre-existing Biome errors (a component named Error, and dangerouslySetInnerHTML) that only surfaced because the theme change re-stages them. Cleared in a separate chore: commit so the feature commit stays theme-only.

Verification

  • tsc --noEmit: clean
  • Biome: 0 errors across changed files
  • vitest: 99 passed, 6 skipped
  • Manually exercised light / system / dark across the app, marketing pages, the RFC editor, code blocks, and diffs.
expand for screenshots! CleanShot 2026-06-29 at 15 29 04 CleanShot 2026-06-29 at 15 30 59 CleanShot 2026-06-29 at 15 31 28 CleanShot 2026-06-29 at 15 31 46

cat-ph added 5 commits June 27, 2026 00:26
Add a three-way Light / System / Dark theme switch, defaulting to the
visitor's OS preference.

- next-themes ThemeProvider using the class strategy; no flash via its
  pre-paint script plus suppressHydrationWarning on <html>
- ThemeToggle in the app top bar and the marketing footer
- Dark palette defined as CSS variables under .dark (P3 + sRGB fallback), so
  the variable-driven UI flips with no per-component changes
- Dark highlight.js syntax tokens, plus dark: variants for the hardcoded
  status colors (diff views, error box)
- Make the CodeMirror editor and Mermaid diagrams theme-aware
These two files predate the biome rules that now flag them and were never
re-linted (lint-staged only checks staged files). The theme change re-stages
them, so resolve the errors to keep the branch lint-clean:

- Rename the error-boundary component Error -> ErrorBoundary, which avoids
  shadowing the global Error (Next.js does not care about the component name)
- Annotate MermaidDiagram's dangerouslySetInnerHTML: it injects SVG that
  mermaid generated from the diagram source, not arbitrary user HTML
…match

@uiw/react-codemirror sets a cm-theme-{light,dark} wrapper class from its
theme prop. Reading next-themes' resolvedTheme during render made the server
emit cm-theme-light while a dark-mode client's first render emitted
cm-theme-dark, a hydration mismatch on the RFC editor pages. Gate the dark
theme behind the same mounted guard ThemeToggle uses: render light on the
first pass (matching SSR), then switch after mount.
The dark palette brightens --cyan while --foreground goes near-white, so the
error boundary "Try again" button (bg-cyan + text-foreground) dropped to ~2:1
contrast in dark mode. Add dark:text-surface so dark mode draws dark text on
the light cyan; light mode keeps its readable dark-on-cyan.
The dark highlight.js override copied most of github-dark but omitted
.hljs-emphasis and .hljs-strong, so they kept the imported light theme color
(#24292e) and rendered near-invisible on the dark code background. Override
both to the github-dark base text color; italic/bold styling is unchanged.
@vercel

vercel Bot commented Jun 29, 2026

Copy link
Copy Markdown
Contributor

@cat-ph is attempting to deploy a commit to the Twixes' projects Team on Vercel.

A member of the Team first needs to authorize it.

@cat-ph cat-ph left a comment

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

@Twixes 👋 this was a bit vibed ngl but tested! 😆 love rfc123 so far, tried looking at an RFC last night and it blasted my eyes haha so I thought this would be useful

Comment thread src/app/error.tsx
import { useEffect } from "react";

export default function Error({
export default function ErrorBoundary({

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

biome was failing here before

});
mermaidInitialized = true;
}
// Re-initialize each render so a theme switch re-themes the diagram.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

maybe not the best but memoized 🤔

@cat-ph cat-ph marked this pull request as ready for review June 29, 2026 12:38
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