Use system theme and apply theme on mount (#6405)

Set ThemeProvider defaultTheme to "system" and enable system preference so the app follows the OS theme. In the theme store, apply the resolved theme to the document immediately on mount so the store is the single source of truth and avoids an initial light flash on fresh origins (e.g. empty localStorage). Minor comment and formatting tweaks in setTheme were also made.

Co-authored-by: Lee Jackson <130007945+Imagineer99@users.noreply.github.com>
This commit is contained in:
Etherll 2026-06-17 19:35:14 +03:00 committed by GitHub
commit c0cd3a506c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 9 additions and 3 deletions

View file

@ -335,7 +335,7 @@ function TauriWrapper({ children }: { children: ReactNode }) {
export function AppProvider({ children }: AppProviderProps) {
return (
<ThemeProvider attribute="class" defaultTheme="light">
<ThemeProvider attribute="class" defaultTheme="system" enableSystem>
<TooltipProvider>
<TauriWrapper>
{children}

View file

@ -50,6 +50,12 @@ function subscribe(cb: () => void) {
applyToDocument(resolveTheme(readStoredTheme()));
cb();
};
// Apply on mount so this store is the single source of truth for the DOM
// class. Without this, initial paint depends solely on next-themes, which on
// a fresh origin (e.g. a new Cloudflare --secure link with empty
// localStorage) falls back to its own default and shows light while the
// control still reads "system".
applyToDocument(resolveTheme(readStoredTheme()));
const onStorage = (e: StorageEvent) => {
if (e.key === STORAGE_KEY || e.key === null) syncTheme();
};
@ -77,8 +83,8 @@ function getServerSnapshot(): Theme {
*/
export function setTheme(next: Theme): void {
if (typeof window === "undefined") return;
// Persist "system" explicitly so next-themes (defaultTheme="light")
// doesn't clobber the choice on reload.
// Persist "system" explicitly so next-themes doesn't clobber the choice on
// reload.
try {
window.localStorage.setItem(STORAGE_KEY, next);
} catch {