mirror of
https://github.com/gogs/gogs.git
synced 2026-05-28 21:30:36 +00:00
42 lines
1.2 KiB
TypeScript
42 lines
1.2 KiB
TypeScript
import { useEffect, useState } from "react";
|
|
|
|
export type Theme = "light" | "dark" | "system";
|
|
|
|
const STORAGE_KEY = "gogs-theme";
|
|
|
|
function systemPrefersDark(): boolean {
|
|
return typeof window !== "undefined" && window.matchMedia("(prefers-color-scheme: dark)").matches;
|
|
}
|
|
|
|
function readStoredTheme(): Theme {
|
|
if (typeof localStorage === "undefined") return "system";
|
|
const v = localStorage.getItem(STORAGE_KEY);
|
|
return v === "light" || v === "dark" || v === "system" ? v : "system";
|
|
}
|
|
|
|
function applyTheme(theme: Theme) {
|
|
const dark = theme === "dark" || (theme === "system" && systemPrefersDark());
|
|
document.documentElement.classList.toggle("dark", dark);
|
|
}
|
|
|
|
export function useTheme() {
|
|
const [theme, setThemeState] = useState<Theme>(readStoredTheme);
|
|
|
|
useEffect(() => {
|
|
applyTheme(theme);
|
|
if (theme !== "system") return;
|
|
const mq = window.matchMedia("(prefers-color-scheme: dark)");
|
|
const onChange = () => applyTheme("system");
|
|
mq.addEventListener("change", onChange);
|
|
return () => mq.removeEventListener("change", onChange);
|
|
}, [theme]);
|
|
|
|
const setTheme = (next: Theme) => {
|
|
localStorage.setItem(STORAGE_KEY, next);
|
|
setThemeState(next);
|
|
applyTheme(next);
|
|
};
|
|
|
|
return { theme, setTheme };
|
|
}
|