ReMe/website/app/theme.ts
jinliyl b8f48c8004
feat(web): add the ReMe Studio frontend (#418)
* feat(web): add the ReMe workspace frontend

* fix(web): use public npm registry in lockfile

* fix(web): address workspace review feedback

* fix(web): protect drafts and report file limits

* fix(web): finish chat streams after tab switches

* feat(web): rename frontend to ReMe Studio
2026-08-11 19:47:59 +08:00

57 lines
1.7 KiB
TypeScript

"use client";
import { create } from "zustand";
export type ThemePreference = "light" | "dark" | "system";
export type ResolvedTheme = "light" | "dark";
const STORAGE_KEY = "reme-theme";
let listeningForSystemTheme = false;
const resolveTheme = (preference: ThemePreference): ResolvedTheme =>
preference === "system" && typeof window !== "undefined"
? window.matchMedia("(prefers-color-scheme: dark)").matches
? "dark"
: "light"
: preference === "dark"
? "dark"
: "light";
const applyTheme = (preference: ThemePreference) => {
const resolved = resolveTheme(preference);
if (typeof document !== "undefined")
document.documentElement.dataset.theme = resolved;
return resolved;
};
interface ThemeState {
preference: ThemePreference;
resolved: ResolvedTheme;
hydrate: () => void;
setPreference: (preference: ThemePreference) => void;
}
export const useThemeStore = create<ThemeState>((set, get) => ({
preference: "system",
resolved: "light",
hydrate: () => {
const saved = localStorage.getItem(STORAGE_KEY);
const preference: ThemePreference =
saved === "light" || saved === "dark" || saved === "system"
? saved
: "system";
set({ preference, resolved: applyTheme(preference) });
if (listeningForSystemTheme) return;
listeningForSystemTheme = true;
window
.matchMedia("(prefers-color-scheme: dark)")
.addEventListener("change", () => {
if (get().preference === "system")
set({ resolved: applyTheme("system") });
});
},
setPreference: (preference) => {
localStorage.setItem(STORAGE_KEY, preference);
set({ preference, resolved: applyTheme(preference) });
},
}));