studio/frontend: keep theme classes mutually exclusive on <html> (#5580)

* studio/frontend: keep theme classes mutually exclusive on <html>

The Sonner Toaster reads next-themes (mounted at provider.tsx with
attribute="class" defaultTheme="light"), so on first mount next-themes
adds a "light" class to <html>. Studio's own setTheme path
(features/settings/stores/theme-store.ts) only toggled "dark", so
after the user picked Dark in settings the document ended up with
html.className = "light dark". Harmless in CSS cascade because the
dark variables override, but reads as a UI defect in devtools and trips
CSS-aware tooling that branches on class lists.

Toggle "light" alongside "dark" in applyToDocument so the two classes
stay mutually exclusive regardless of how next-themes seeded the
initial class.

* studio/frontend: shorten theme-toggle comment

---------

Co-authored-by: danielhanchen <michaelhan2050@gmail.com>
This commit is contained in:
Daniel Han 2026-05-19 06:56:15 -07:00 committed by GitHub
commit 0fb86e15b9
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -32,7 +32,12 @@ function resolveTheme(theme: Theme): ResolvedTheme {
function applyToDocument(resolved: ResolvedTheme) {
if (typeof document === "undefined") return;
document.documentElement.classList.toggle("dark", resolved === "dark");
// Keep "dark"/"light" mutually exclusive. next-themes (via Sonner)
// adds "light" on first mount; without the explicit toggle we'd end
// up with `class="light dark"` after a switch.
const cl = document.documentElement.classList;
cl.toggle("dark", resolved === "dark");
cl.toggle("light", resolved === "light");
}
const listeners = new Set<() => void>();