feat: add dark / system theme toggle#14
Open
cat-ph wants to merge 5 commits into
Open
Conversation
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.
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
commented
Jun 29, 2026
| import { useEffect } from "react"; | ||
|
|
||
| export default function Error({ | ||
| export default function ErrorBoundary({ |
| }); | ||
| mermaidInitialized = true; | ||
| } | ||
| // Re-initialize each render so a theme switch re-themes the diagram. |
Author
There was a problem hiding this comment.
maybe not the best but memoized 🤔
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Adds a three-way Light / System / Dark theme toggle, defaulting to the visitor's OS preference.
ThemeProvider(next-themes,classstrategy) wired into the root layout; no-flash via its pre-paint script +suppressHydrationWarningon<html>.ThemeToggle(Light / System / Dark) in the app top bar and the marketing footer..dark(P3 + sRGB fallback). Because the UI is already variable-driven, the whole surface flips with almost no per-component changes.dark:variants for the few hardcoded status colors (diff views, error box).Notes
--gray-5stays the "barely off the background" tint,--gray-90the strongest text — so existing class usage keeps its meaning.error.tsx/MermaidDiagram.tsxcarried pre-existing Biome errors (a component namedError, anddangerouslySetInnerHTML) that only surfaced because the theme change re-stages them. Cleared in a separatechore:commit so the feature commit stays theme-only.Verification
tsc --noEmit: cleanvitest: 99 passed, 6 skippedexpand for screenshots!