diff --git a/web/__test__/store/theme.test.ts b/web/__test__/store/theme.test.ts index e9cb7246ad..f301ac2f2d 100644 --- a/web/__test__/store/theme.test.ts +++ b/web/__test__/store/theme.test.ts @@ -286,5 +286,17 @@ describe('Theme Store', () => { vi.restoreAllMocks(); }); + + it('should remove stale dark classes when the DOM theme is light', () => { + document.documentElement.style.setProperty('--theme-name', 'white'); + originalDocumentElementAddClass.call(document.documentElement.classList, 'dark'); + originalAddClassFn.call(document.body.classList, 'dark'); + + const store = createStore(); + + expect(document.documentElement.classList.remove).toHaveBeenCalledWith('dark'); + expect(document.body.classList.remove).toHaveBeenCalledWith('dark'); + expect(store.darkMode).toBe(false); + }); }); }); diff --git a/web/src/store/theme.ts b/web/src/store/theme.ts index a3d2f5a599..cd0f6178ef 100644 --- a/web/src/store/theme.ts +++ b/web/src/store/theme.ts @@ -48,6 +48,9 @@ const getCssVar = (name: string): string => { const readDomThemeName = () => getCssVar('--theme-name'); +const isDarkThemeName = (themeName: string) => + DARK_UI_THEMES.includes(themeName as (typeof DARK_UI_THEMES)[number]); + const syncDarkClass = (method: 'add' | 'remove') => { if (!isDomAvailable()) return; document.documentElement.classList[method]('dark'); @@ -98,12 +101,6 @@ export const useThemeStore = defineStore('theme', () => { const devOverride = ref(false); const darkMode = ref(false); - // Initialize dark mode from CSS variable set by PHP or any pre-applied .dark class - if (isDomAvailable()) { - darkMode.value = isDarkModeActive(); - bootstrapDarkClass(darkMode); - } - // Lazy query - only executes when explicitly called const { load, onResult, onError } = useLazyQuery(GET_THEME_QUERY, null, { fetchPolicy: 'cache-and-network', @@ -208,16 +205,19 @@ export const useThemeStore = defineStore('theme', () => { watch( () => theme.value.name, (themeName) => { - const isDark = DARK_UI_THEMES.includes(themeName as (typeof DARK_UI_THEMES)[number]); - applyDarkClass(isDark, darkMode); + applyDarkClass(isDarkThemeName(themeName), darkMode); }, { immediate: false } ); // Initialize theme from DOM on store creation - const domThemeName = themeName.value; - if (domThemeName && domThemeName !== DEFAULT_THEME.name) { - theme.value.name = domThemeName; + const domThemeName = readDomThemeName(); + if (domThemeName) { + setTheme({ name: domThemeName }); + applyDarkClass(isDarkThemeName(domThemeName), darkMode); + } else if (isDomAvailable()) { + darkMode.value = isDarkModeActive(); + bootstrapDarkClass(darkMode); } return {