Theme
Give every surface one light, dark, or system preference and store it in Chrome storage instead of page-local state.
Initialize on mount
The generated surface root initializes the stored preference and applies the resolved theme before the interface renders.
import { initializeTheme } from "@/shared/theme";
await initializeTheme();Read the current theme
import {
getThemePreference,
getSystemTheme,
resolveThemePreference,
} from "@/shared/theme";
// What the user chose: "light" | "dark" | "system"
const pref = await getThemePreference();
// What the OS is set to: "light" | "dark"
const system = getSystemTheme();
// What's actually applied — resolves "system" to the OS value
const resolved = resolveThemePreference();Change the theme
import { setThemePreference, applyThemePreference } from "@/shared/theme";
// Persist and apply: "light" | "dark" | "system"
await setThemePreference("dark");
// Apply without persisting (useful for previews)
applyThemePreference("dark");Subscribe to changes
Subscribe when product code must react beyond CSS. The provider already updates surface styles when the stored preference or operating-system theme changes.
import { subscribeToThemeChange } from "@/shared/theme";
const unsubscribe = subscribeToThemeChange((resolved) => {
console.log("Theme changed to:", resolved); // "light" | "dark"
});
// Call unsubscribe() when the component unmountsSystem mode
System mode follows prefers-color-scheme and updates while the surface is open. Build colors from the shadcn tokens in globals.css so both themes remain coherent.
