Skip to content

ThemeToggle briefly shows the wrong icon on first paint because theme state initializes to "light" before the correcting effect runs #208

Description

@chonilius

src/context/ThemeContext.tsx#ThemeProvider initializes React state unconditionally:

const [theme, setTheme] = useState<Theme>("light");

The actual applied theme (dark or light) is decided synchronously before hydration by
the inline themeInitScript in layout.tsx, which adds the dark class straight to
<html>. ThemeProvider's useEffect then reads that class back to correct its own
theme state:

useEffect(() => {
  setTheme(document.documentElement.classList.contains("dark") ? "dark" : "light");
  ...
}, []);

Between first paint and this effect running, theme is "light" regardless of the
visitor's actual preference. src/components/ui/ThemeToggle.tsx renders its icon
directly from this state:

{theme === "dark" ? <Sun className="h-4 w-4" /> : <Moon className="h-4 w-4" />}

For a visitor whose page is actually rendering in dark mode (via a stored preference or
prefers-color-scheme: dark), the toggle button shows a Moon icon (meaning "click to
go dark") for one render/paint even though the page is already dark — the icon is
momentarily backwards relative to the real state, a small but visible flash on every
page load in dark mode.

Suggested fix: read the initial theme synchronously via a lazy useState initializer
(useState<Theme>(() => document.documentElement.classList.contains("dark") ? "dark" : "light"))
instead of hardcoding "light" and correcting it after the fact — safe here since
ThemeProvider is already a Client Component executing after the theme-init script
has run.

Metadata

Metadata

Labels

Stellar WaveIssues in the Stellar wave programbugSomething isn't workingenhancementNew feature or requesthelp wantedExtra attention is neededvery hardVery difficult task, expert-level effort required

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions