@@ -1,6 +1,7 @@
|
||||
import type { Theme } from "@/modules/auth/types/auth.types";
|
||||
import { create } from "zustand";
|
||||
import { persist } from "zustand/middleware";
|
||||
import { applyTheme, getSavedTheme, getCurrentTheme } from "@/modules/theme-changer/utils/apply.theme";
|
||||
|
||||
interface ThemeState {
|
||||
theme: Theme;
|
||||
@@ -10,26 +11,20 @@ interface ThemeState {
|
||||
|
||||
export const useThemeStore = create<ThemeState>()(
|
||||
persist(
|
||||
(set) => ({
|
||||
theme: "dark",
|
||||
(set, get) => ({
|
||||
theme: "dark" as Theme,
|
||||
toggleTheme: () => {
|
||||
set((state) => {
|
||||
const newTheme = state.theme === "dark" ? "light" : "dark";
|
||||
// Применяем класс к documentElement
|
||||
if (newTheme === "dark") {
|
||||
document.documentElement.classList.add("dark");
|
||||
} else {
|
||||
document.documentElement.classList.remove("dark");
|
||||
}
|
||||
return { theme: newTheme };
|
||||
});
|
||||
const currentTheme = getCurrentTheme();
|
||||
const newThemeType = currentTheme === "dark" || currentTheme === "nightowl" || currentTheme === "sunset" || currentTheme === "forest" || currentTheme === "ocean" || currentTheme === "coffee"
|
||||
? "light"
|
||||
: "dark";
|
||||
// Переключаемся между light и dark базовыми темами
|
||||
const newTheme = newThemeType === "dark" ? "dark" : "light";
|
||||
applyTheme(newTheme);
|
||||
set({ theme: newTheme as Theme });
|
||||
},
|
||||
setTheme: (theme: Theme) => {
|
||||
if (theme === "dark") {
|
||||
document.documentElement.classList.add("dark");
|
||||
} else {
|
||||
document.documentElement.classList.remove("dark");
|
||||
}
|
||||
applyTheme(theme);
|
||||
set({ theme });
|
||||
},
|
||||
}),
|
||||
@@ -38,17 +33,3 @@ export const useThemeStore = create<ThemeState>()(
|
||||
},
|
||||
),
|
||||
);
|
||||
|
||||
// Инициализация темы при загрузке
|
||||
if (typeof window !== "undefined") {
|
||||
const storedTheme = localStorage.getItem("theme-storage");
|
||||
if (storedTheme) {
|
||||
const { state } = JSON.parse(storedTheme);
|
||||
if (state.theme === "dark") {
|
||||
document.documentElement.classList.add("dark");
|
||||
}
|
||||
} else {
|
||||
// По умолчанию dark
|
||||
document.documentElement.classList.add("dark");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,20 +1,56 @@
|
||||
import React from "react";
|
||||
import { useThemeStore } from "../stores/theme.store";
|
||||
import React, { useState, useEffect } from "react";
|
||||
import { FiSun, FiMoon } from "react-icons/fi";
|
||||
import { getCurrentTheme, toggleDarkLight, getSavedTheme } from "../../theme-changer/utils/apply.theme";
|
||||
import { themes } from "../../theme-changer/config/theme.config";
|
||||
|
||||
export const ThemeToggle: React.FC = () => {
|
||||
const { theme, toggleTheme } = useThemeStore();
|
||||
const [currentTheme, setCurrentTheme] = useState<string>(() => getSavedTheme());
|
||||
|
||||
const currentThemeData = themes.find((t) => t.id === currentTheme);
|
||||
const isDark = currentThemeData?.type === "dark";
|
||||
|
||||
const handleClick = () => {
|
||||
const newTheme = toggleDarkLight();
|
||||
setCurrentTheme(newTheme);
|
||||
};
|
||||
|
||||
// Инициализация при монтировании
|
||||
useEffect(() => {
|
||||
const saved = getSavedTheme();
|
||||
const current = getCurrentTheme() || saved;
|
||||
setCurrentTheme(current);
|
||||
}, []);
|
||||
|
||||
// Слушаем изменения темы из других компонентов
|
||||
useEffect(() => {
|
||||
const handleThemeChange = (e: Event) => {
|
||||
const event = e as CustomEvent;
|
||||
setCurrentTheme(event.detail.theme);
|
||||
};
|
||||
window.addEventListener("themechange", handleThemeChange);
|
||||
return () => window.removeEventListener("themechange", handleThemeChange);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<button
|
||||
onClick={toggleTheme}
|
||||
className="p-2 rounded-lg bg-gray-200 dark:bg-gray-800 hover:bg-gray-300 dark:hover:bg-gray-700 transition-colors duration-200"
|
||||
aria-label="Toggle theme"
|
||||
onClick={handleClick}
|
||||
className="p-2 rounded-lg transition-colors duration-200"
|
||||
style={{
|
||||
backgroundColor: "var(--bg-secondary)",
|
||||
}}
|
||||
onMouseEnter={(e) => {
|
||||
e.currentTarget.style.backgroundColor = "var(--bg-tertiary)";
|
||||
}}
|
||||
onMouseLeave={(e) => {
|
||||
e.currentTarget.style.backgroundColor = "var(--bg-secondary)";
|
||||
}}
|
||||
aria-label="Переключить тему"
|
||||
title={isDark ? "Переключить на светлую тему" : "Переключить на тёмную тему"}
|
||||
>
|
||||
{theme === "dark" ? (
|
||||
<FiSun className="w-5 h-5 text-yellow-500" />
|
||||
{isDark ? (
|
||||
<FiSun className="w-5 h-5" style={{ color: "var(--accent)" }} />
|
||||
) : (
|
||||
<FiMoon className="w-5 h-5 text-gray-700" />
|
||||
<FiMoon className="w-5 h-5" style={{ color: "var(--text-secondary)" }} />
|
||||
)}
|
||||
</button>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user