feat(ui): persist theme preference

Persist system/light/dark theme mode in app config and default new installs to system so the UI follows OS theme unless overridden.
This commit is contained in:
Shantur Rathore
2026-02-03 19:42:24 +00:00
parent 02407e0f7a
commit d98d519fd3
2 changed files with 6 additions and 15 deletions

View File

@@ -78,12 +78,12 @@ const resolvePaletteColors = (dark: boolean): ResolvedPaletteColors => {
export function ThemeProvider(props: { children: JSX.Element }) {
const mediaQuery = typeof window !== "undefined" ? window.matchMedia("(prefers-color-scheme: dark)") : null
const { themePreference } = useConfig()
const { themePreference, setThemePreference } = useConfig()
const [isDark, setIsDarkSignal] = createSignal(true)
const [themeMode, setThemeModeSignal] = createSignal<ThemeMode>(themePreference())
const [hasUserOverride, setHasUserOverride] = createSignal(false)
const [themeRevision, setThemeRevision] = createSignal(0)
const themeMode = () => themePreference() as ThemeMode
const resolveDarkTheme = () => {
const mode = themeMode()
if (mode === "dark") return true
@@ -111,12 +111,6 @@ export function ThemeProvider(props: { children: JSX.Element }) {
applyResolvedTheme()
})
createEffect(() => {
const preference = themePreference()
if (hasUserOverride()) return
setThemeModeSignal(preference)
})
onMount(() => {
if (!mediaQuery) return
const handleSystemThemeChange = () => {
@@ -131,10 +125,7 @@ export function ThemeProvider(props: { children: JSX.Element }) {
})
const setThemeMode = (mode: ThemeMode) => {
setHasUserOverride(true)
setThemeModeSignal(mode)
// Persistence is intentionally implemented later.
// When we wire it up, this should call `setThemePreference(mode)`.
setThemePreference(mode)
}
const cycleThemeMode = () => {

View File

@@ -194,7 +194,7 @@ const [isConfigLoaded, setIsConfigLoaded] = createSignal(false)
const preferences = createMemo<Preferences>(() => internalConfig().preferences)
const recentFolders = createMemo<RecentFolder[]>(() => internalConfig().recentFolders ?? [])
const opencodeBinaries = createMemo<OpenCodeBinary[]>(() => internalConfig().opencodeBinaries ?? [])
const themePreference = createMemo<ThemePreference>(() => internalConfig().theme ?? "dark")
const themePreference = createMemo<ThemePreference>(() => internalConfig().theme ?? "system")
let loadPromise: Promise<void> | null = null
function normalizeConfig(config?: ConfigData | null): ConfigData {
@@ -202,7 +202,7 @@ function normalizeConfig(config?: ConfigData | null): ConfigData {
preferences: normalizePreferences(config?.preferences),
recentFolders: (config?.recentFolders ?? []).map((folder) => ({ ...folder })),
opencodeBinaries: (config?.opencodeBinaries ?? []).map((binary) => ({ ...binary })),
theme: config?.theme ?? "dark",
theme: config?.theme ?? "system",
}
}