blog-fs/commons/theme.tsx

57 lines
1.3 KiB
TypeScript
Raw Normal View History

2021-05-02 20:04:54 +08:00
import React, { createContext, FC, useContext, useEffect, useState } from "react";
const getInitialTheme = (): Mode => {
if (typeof window === "undefined") {
return 'auto';
}
const text = window?.localStorage?.getItem('theme');
switch (text) {
case 'dark': return 'dark';
case 'light': return 'light';
default: return 'auto';
}
};
type RawMode = "light" | "dark";
type Mode = RawMode | "auto";
interface Content {
mode: Mode;
setMode: (mode: Mode) => void;
}
export const ThemeContext = createContext<Content>({
mode: 'error' as Mode,
setMode: (_) => {console.log},
});
export const ThemeProvider: FC = ({ children }) => {
const [mode, setMode] = useState<Mode>(() => getInitialTheme());
useEffect(() => {
if (window) {
localStorage.setItem("theme", mode);
let _mode = mode;
if (_mode === "auto") {
_mode =
window.matchMedia?.("(prefers-color-scheme: dark)").matches ? "dark" : "light";
}
if (_mode === "dark") {
window.document.documentElement.classList.add("dark");
} else {
window.document.documentElement.classList.remove("dark");
}
}
}, [mode]);
return (
<ThemeContext.Provider value={{ mode, setMode }}>
{children}
</ThemeContext.Provider>
);
};
export function useTheme () {
return useContext(ThemeContext);
}