button update

This commit is contained in:
2026-03-31 14:39:04 +07:00
parent 0f7f01310e
commit bd51ac5ddf
8 changed files with 582 additions and 149 deletions
+65
View File
@@ -0,0 +1,65 @@
import React, {
createContext,
useContext,
useState,
useLayoutEffect,
useEffect,
} from "react";
type ThemeContextType = {
isDark: boolean;
toggleDark: () => void;
};
const ThemeContext = createContext<ThemeContextType | undefined>(undefined);
export const ThemeProvider = ({ children }: { children: React.ReactNode }) => {
const [isDark, setIsDark] = useState(() => {
if (typeof window === "undefined") return false;
const saved = localStorage.getItem("theme");
if (saved) return saved === "dark";
return document.documentElement.classList.contains("dark");
});
// Синхронизация с DOM (classList)
useLayoutEffect(() => {
if (isDark) {
document.documentElement.classList.add("dark");
} else {
document.documentElement.classList.remove("dark");
}
}, [isDark]);
// Слушатель системной темы
useEffect(() => {
const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
const handleChange = (e: MediaQueryListEvent) => {
if (!localStorage.getItem("theme")) {
setIsDark(e.matches);
}
};
mediaQuery.addEventListener("change", handleChange);
return () => mediaQuery.removeEventListener("change", handleChange);
}, []);
const toggleDark = () => {
const nextDark = !isDark;
localStorage.setItem("theme", nextDark ? "dark" : "light");
setIsDark(nextDark);
};
return (
<ThemeContext.Provider value={{ isDark, toggleDark }}>
{children}
</ThemeContext.Provider>
);
};
// Обновленный хук, который теперь берет данные из общего Контекста
export const useTheme = () => {
const context = useContext(ThemeContext);
if (!context) {
throw new Error("useTheme must be used within a ThemeProvider");
}
return context;
};