import { useCallback, useEffect, useState } from "react"; /** * Color scheme preference (system / light / dark). * * The preference lives in the `ob-color-scheme` cookie so the article template * can read it server side and render `data-color-scheme` on `` and * `
` before the first paint. The site script for the 2026 template * (`ob.2026.application.min.js`) owns the same cookie for the toolbar user menu * toggle, so both write the cookie, apply the attributes, and dispatch * `COLOR_SCHEME_CHANGE_EVENT` to keep every toggle on the page in sync. */ export type ColorSchemePreference = "auto" | "light" | "dark"; const COOKIE_NAME = "ob-color-scheme"; const COOKIE_MAX_AGE = 60 * 60 * 24 * 365; const DEFAULT_PREFERENCE: ColorSchemePreference = "auto"; const PREFERENCES: ColorSchemePreference[] = ["auto", "light", "dark"]; /** Dispatched on `window` whenever the preference changes. */ export const COLOR_SCHEME_CHANGE_EVENT = "ob:colorschemechange"; function isColorSchemePreference(value: unknown): value is ColorSchemePreference { return typeof value === "string" && PREFERENCES.includes(value as ColorSchemePreference); } export function getColorSchemePreference(): ColorSchemePreference { if (typeof document === "undefined") return DEFAULT_PREFERENCE; let match = document.cookie.match(new RegExp(`(?:^|;\\s*)${COOKIE_NAME}=([^;]*)`)); let value = match ? decodeURIComponent(match[1]) : null; return isColorSchemePreference(value) ? value : DEFAULT_PREFERENCE; } export function setColorSchemePreference(preference: ColorSchemePreference) { if (typeof document === "undefined" || !isColorSchemePreference(preference)) return; let secure = window.location.protocol === "https:" ? ";secure" : ""; document.cookie = `${COOKIE_NAME}=${preference};path=/;max-age=${COOKIE_MAX_AGE};samesite=lax${secure}`; /* * Both elements are updated: `` so the browser applies `color-scheme` * to scrollbars and native controls, `` because Designsystemet declares * the light tokens on `:root` as well (`:root, [data-color-scheme="light"]`). */ document.documentElement.dataset.colorScheme = preference; if (document.body) document.body.dataset.colorScheme = preference; window.dispatchEvent(new CustomEvent(COLOR_SCHEME_CHANGE_EVENT, { detail: preference })); } /** Reads the stored preference and keeps it in sync with other toggles on the page. */ export function useColorSchemePreference(): [ColorSchemePreference, (value: ColorSchemePreference) => void] { let [preference, setPreference] = useState