mirror of
https://github.com/Dvorinka/Bookra.git
synced 2026-06-05 04:52:59 +00:00
cleanup
This commit is contained in:
@@ -0,0 +1,88 @@
|
||||
import {
|
||||
createContext,
|
||||
createEffect,
|
||||
createSignal,
|
||||
ParentComponent,
|
||||
useContext,
|
||||
} from "solid-js";
|
||||
|
||||
type Theme = "light" | "dark" | "system";
|
||||
|
||||
const STORAGE_KEY = "bookra-theme";
|
||||
|
||||
function getInitialTheme(): Theme {
|
||||
if (typeof window === "undefined") return "system";
|
||||
const stored = localStorage.getItem(STORAGE_KEY) as Theme | null;
|
||||
return stored ?? "system";
|
||||
}
|
||||
|
||||
function getResolvedTheme(theme: Theme): "light" | "dark" {
|
||||
if (theme === "system") {
|
||||
return window.matchMedia("(prefers-color-scheme: dark)").matches
|
||||
? "dark"
|
||||
: "light";
|
||||
}
|
||||
return theme;
|
||||
}
|
||||
|
||||
type ThemeContextValue = {
|
||||
theme: () => Theme;
|
||||
resolvedTheme: () => "light" | "dark";
|
||||
setTheme: (theme: Theme) => void;
|
||||
toggle: () => void;
|
||||
};
|
||||
|
||||
const ThemeContext = createContext<ThemeContextValue>();
|
||||
|
||||
export const ThemeProvider: ParentComponent = (props) => {
|
||||
const [theme, setThemeSignal] = createSignal<Theme>(getInitialTheme());
|
||||
const [resolvedTheme, setResolvedTheme] = createSignal<"light" | "dark">(
|
||||
getResolvedTheme(getInitialTheme())
|
||||
);
|
||||
|
||||
const applyTheme = (t: Theme) => {
|
||||
const resolved = getResolvedTheme(t);
|
||||
setResolvedTheme(resolved);
|
||||
|
||||
const root = document.documentElement;
|
||||
root.classList.remove("light", "dark");
|
||||
root.classList.add(resolved);
|
||||
root.setAttribute("data-theme", resolved);
|
||||
};
|
||||
|
||||
createEffect(() => {
|
||||
const t = theme();
|
||||
localStorage.setItem(STORAGE_KEY, t);
|
||||
applyTheme(t);
|
||||
});
|
||||
|
||||
if (typeof window !== "undefined") {
|
||||
const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
|
||||
mediaQuery.addEventListener("change", () => {
|
||||
if (theme() === "system") {
|
||||
applyTheme("system");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
const setTheme = (t: Theme) => setThemeSignal(t);
|
||||
|
||||
const toggle = () => {
|
||||
const current = resolvedTheme();
|
||||
setTheme(current === "light" ? "dark" : "light");
|
||||
};
|
||||
|
||||
return (
|
||||
<ThemeContext.Provider value={{ theme, resolvedTheme, setTheme, toggle }}>
|
||||
{props.children}
|
||||
</ThemeContext.Provider>
|
||||
);
|
||||
};
|
||||
|
||||
export function useTheme() {
|
||||
const context = useContext(ThemeContext);
|
||||
if (!context) {
|
||||
throw new Error("ThemeProvider is missing from the component tree.");
|
||||
}
|
||||
return context;
|
||||
}
|
||||
Reference in New Issue
Block a user