diff --git a/frontend-modern/src/components/FirstRunSetup.tsx b/frontend-modern/src/components/FirstRunSetup.tsx index 10c670e12..f288f28f4 100644 --- a/frontend-modern/src/components/FirstRunSetup.tsx +++ b/frontend-modern/src/components/FirstRunSetup.tsx @@ -1,6 +1,7 @@ import { Component, createSignal, Show, onMount } from 'solid-js'; import { showSuccess, showError } from '@/utils/toast'; import { copyToClipboard } from '@/utils/clipboard'; +import { STORAGE_KEYS } from '@/constants'; export const FirstRunSetup: Component = () => { const [username, setUsername] = createSignal('admin'); @@ -15,10 +16,44 @@ export const FirstRunSetup: Component = () => { const [savedPassword, setSavedPassword] = createSignal(''); const [savedToken, setSavedToken] = createSignal(''); const [copied, setCopied] = createSignal<'password' | 'token' | null>(null); + const [themeMode, setThemeMode] = createSignal<'system' | 'light' | 'dark'>('system'); + const applyTheme = (mode: 'system' | 'light' | 'dark') => { + if (mode === 'light') { + document.documentElement.classList.remove('dark'); + localStorage.setItem(STORAGE_KEYS.DARK_MODE, 'false'); + } else if (mode === 'dark') { + document.documentElement.classList.add('dark'); + localStorage.setItem(STORAGE_KEYS.DARK_MODE, 'true'); + } else { + // System preference + localStorage.removeItem(STORAGE_KEYS.DARK_MODE); + if (window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.documentElement.classList.add('dark'); + } else { + document.documentElement.classList.remove('dark'); + } + } + }; + onMount(() => { - // Force dark mode for setup screen - document.documentElement.classList.add('dark'); + // Check for saved theme preference + const savedTheme = localStorage.getItem(STORAGE_KEYS.DARK_MODE); + if (savedTheme === 'false') { + setThemeMode('light'); + document.documentElement.classList.remove('dark'); + } else if (savedTheme === 'true') { + setThemeMode('dark'); + document.documentElement.classList.add('dark'); + } else { + // No saved preference - use system preference + setThemeMode('system'); + if (window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.documentElement.classList.add('dark'); + } else { + document.documentElement.classList.remove('dark'); + } + } }); const generatePassword = () => { @@ -253,6 +288,58 @@ IMPORTANT: Keep these credentials secure! + {/* Theme Selection */} +
+ +
+ + + +
+

+ {themeMode() === 'system' + ? 'Using your operating system theme preference' + : `Using ${themeMode()} mode`} +

+
{/* Info Box */}
diff --git a/frontend-modern/src/components/Login.tsx b/frontend-modern/src/components/Login.tsx index 269275eb5..806b01d01 100644 --- a/frontend-modern/src/components/Login.tsx +++ b/frontend-modern/src/components/Login.tsx @@ -1,5 +1,6 @@ import { Component, createSignal, Show, onMount, lazy, Suspense } from 'solid-js'; import { setBasicAuth } from '@/utils/apiClient'; +import { STORAGE_KEYS } from '@/constants'; // Force include FirstRunSetup with lazy loading const FirstRunSetup = lazy(() => import('./FirstRunSetup').then(m => ({ default: m.FirstRunSetup }))); @@ -17,8 +18,20 @@ export const Login: Component = (props) => { const [loadingAuth, setLoadingAuth] = createSignal(true); onMount(async () => { - // Force dark mode for login screen - document.documentElement.classList.add('dark'); + // Apply saved theme preference from localStorage + const savedTheme = localStorage.getItem(STORAGE_KEYS.DARK_MODE); + if (savedTheme === 'false') { + document.documentElement.classList.remove('dark'); + } else if (savedTheme === 'true') { + document.documentElement.classList.add('dark'); + } else { + // No saved preference - use system preference + if (window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.documentElement.classList.add('dark'); + } else { + document.documentElement.classList.remove('dark'); + } + } console.log('[Login] Starting auth check...'); try {