Shared Theme Context - 2

Created Diff never expires
4 removals
22 lines
42 additions
57 lines
import { useEffect, useState } from "react";
import {
createElement,
createContext,
type Dispatch,
type PropsWithChildren,
type SetStateAction,
useContext,
useEffect,
useMemo,
useState,
} from "react";



type Theme = "light" | "dark";
type Theme = "light" | "dark";


export function useTheme() {

interface ThemeContextValue {
theme: Theme;
setTheme: Dispatch<SetStateAction<Theme>>;
toggle: () => void;
}


const ThemeContext = createContext<ThemeContextValue | null>(null);


export function ThemeProvider({ children }: PropsWithChildren) {
const [theme, setTheme] = useState<Theme>(() => {
const [theme, setTheme] = useState<Theme>(() => {
if (typeof window !== "undefined") {
if (typeof window !== "undefined") {
return (localStorage.getItem("theme") as Theme) || "light";
return (localStorage.getItem("theme") as Theme) || "light";
}
}
return "light";
return "light";
});
});



useEffect(() => {
useEffect(() => {
const root = document.documentElement;
const root = document.documentElement;
root.classList.toggle("dark", theme === "dark");
root.classList.toggle("dark", theme === "dark");
localStorage.setItem("theme", theme);
localStorage.setItem("theme", theme);
}, [theme]);
}, [theme]);



const toggle = () => setTheme((t) => (t === "light" ? "dark" : "light"));
const toggle = () => setTheme((t) => (t === "light" ? "dark" : "light"));
const value = useMemo(() => ({ theme, setTheme, toggle }), [theme]);


return { theme, setTheme, toggle };

return createElement(ThemeContext.Provider, { value }, children);
}


export function useTheme() {
const context = useContext(ThemeContext);
if (!context) {
throw new Error("useTheme must be used within a ThemeProvider");
}
return context;
}
}