Hooks
useTheme
The current theme as external DOM state, with no flash on load.
The current theme as external DOM state. The hook does not store the theme itself — it reads the data-theme attribute on <html>, so a theme change from anywhere in the app reaches everyone at once.
Example
- Выбор пользователя
- dark
- Что на экране
- dark
Меняется тема всего сайта — состояние живёт в атрибуте на <html>, а не внутри компонента.
import { useTheme } from "@toimetdev/pathlogs-hooks";
function Toggle() {
const { preference, resolved, setTheme, toggle } = useTheme();
return (
<button onClick={toggle}>
{resolved === "dark" ? "Light" : "Dark"}
</button>
);
}A ready-made switch already exists — ThemeToggle from @toimetdev/pathlogs-core. The hook is for when the switch is your own, or the theme feeds into logic: the colour of a chart, say.
What it returns
| Prop | Type | Default | Description |
|---|---|---|---|
preference | "light" | "dark" | "system" | — | What the user chose. |
resolved | "light" | "dark" | — | «system» already resolved into what is actually on screen. |
setTheme | (theme: ThemePreference) => void | — | Applies the theme and remembers the choice. |
toggle | () => void | — | Switches between light and dark. «system» resolves to the opposite of the current one. |
preference"light" | "dark" | "system"What the user chose.
resolved"light" | "dark"«system» already resolved into what is actually on screen.
setTheme(theme: ThemePreference) => voidApplies the theme and remembers the choice.
toggle() => voidSwitches between light and dark. «system» resolves to the opposite of the current one.
The only argument is the localStorage key ("theme" by default). It must match the key passed to themeScript().
The flash on load
The theme has to be applied before the first paint, or the page flashes. That is what the tiny synchronous script in <head> is for:
import { themeScript } from "@toimetdev/pathlogs-tokens";
<html lang="en" suppressHydrationWarning>
<head>
<script dangerouslySetInnerHTML={{ __html: themeScript() }} />
</head>
</html>The subscription watches both the attribute and the system setting; the latter only matters while system is selected.
Without React
The same operations are available as plain functions — called by the inline script and by the tests alike:
import {
getThemePreference,
getResolvedTheme,
setThemePreference,
toggleTheme,
subscribeTheme,
themeScript,
} from "@toimetdev/pathlogs-tokens";Writing to localStorage can fail (private mode, cookies disabled) — and that does not break the switch: the theme is applied regardless, it just will not survive a reload.