| "use client"; |
|
|
| import * as React from "react"; |
|
|
| type Theme = "dark" | "light"; |
|
|
| interface ThemeContextType { |
| theme: Theme; |
| toggleTheme: () => void; |
| } |
|
|
| const ThemeContext = React.createContext<ThemeContextType | undefined>(undefined); |
|
|
| |
| |
| |
| |
| export function ThemeProvider({ children }: { children: React.ReactNode }) { |
| const [theme, setTheme] = React.useState<Theme>("light"); |
|
|
| |
| React.useEffect(() => { |
| const savedTheme = localStorage.getItem("theme") as Theme; |
| const systemTheme = window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light"; |
| |
| const initialTheme = savedTheme || systemTheme; |
| setTheme(initialTheme); |
| document.documentElement.classList.toggle("dark", initialTheme === "dark"); |
| }, []); |
|
|
| const toggleTheme = React.useCallback(() => { |
| setTheme((prev) => { |
| const newTheme = prev === "light" ? "dark" : "light"; |
| localStorage.setItem("theme", newTheme); |
| document.documentElement.classList.toggle("dark", newTheme === "dark"); |
| return newTheme; |
| }); |
| }, []); |
|
|
| return ( |
| <ThemeContext.Provider value={{ theme, toggleTheme }}> |
| {children} |
| </ThemeContext.Provider> |
| ); |
| } |
|
|
| export const useTheme = () => { |
| const context = React.useContext(ThemeContext); |
| if (!context) throw new Error("useTheme must be used within a ThemeProvider"); |
| return context; |
| }; |
|
|