Initial commit: TopSysOps site + admin panel
Multi-page public site (Next.js), Node/Express backend with Postgres, and Vite admin/account app, restructured from a single-page layout into dedicated service, promotions, cases, about, FAQ, and blog pages for SEO. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013otXCiTZsxdZ4SJKZ9wUky
This commit is contained in:
commit
130c5382cd
108 files changed
+7146
No files matched your search
@@ -0,0 +1,35 @@
|
||||
'use client';
|
||||
|
||||
import { createContext, useContext, useEffect, useState } from 'react';
|
||||
|
||||
const ThemeContext = createContext({ dark: false, toggle: () => {} });
|
||||
|
||||
export const useTheme = () => useContext(ThemeContext);
|
||||
|
||||
export function ThemeProvider({ children }) {
|
||||
// Инлайн-скрипт в layout.jsx уже выставляет класс "dark" на <html> ДО гидратации
|
||||
// (чтобы не было мигания темы). Читаем этот класс напрямую при монтировании.
|
||||
const [dark, setDark] = useState(() => {
|
||||
if (typeof document === 'undefined') return false;
|
||||
return document.documentElement.classList.contains('dark');
|
||||
});
|
||||
|
||||
// Побочные эффекты (DOM-класс, localStorage) вынесены в отдельный useEffect,
|
||||
// а не в апдейтер состояния - React может вызвать функцию апдейтера больше
|
||||
// одного раза за один рендер, и тогда classList.toggle сработал бы дважды,
|
||||
// фактически отменяя переключение (баг "не срабатывает" / "снова светлая").
|
||||
useEffect(() => {
|
||||
document.documentElement.classList.toggle('dark', dark);
|
||||
try {
|
||||
localStorage.setItem('ts-theme', dark ? 'dark' : 'light');
|
||||
} catch (e) {
|
||||
// localStorage unavailable - theme just won't persist
|
||||
}
|
||||
}, [dark]);
|
||||
|
||||
return (
|
||||
<ThemeContext.Provider value={{ dark, toggle: () => setDark((d) => !d) }}>
|
||||
{children}
|
||||
</ThemeContext.Provider>
|
||||
);
|
||||
}
|
||||
Reference in new issue
Block a user