// ThemeToggle — flips the `.dark` class on . Persists choice // to the `voltro:theme` cookie so the server can bake the correct // class on the next request (and `themeBootScript` can sync the // initial paint without round-tripping localStorage). // // Component is interactive — when used inside a static page, mark // the surrounding island as `interaction` strategy. import { useEffect, useState, type HTMLAttributes, type ReactNode } from 'react' import { Button } from '../primitives/button' import { cn } from '../cn' import { THEME_COOKIE, setCookie } from '../cookies' /** * Inline script to drop into
. Reads the `voltro:theme` cookie * (set by ThemeToggle / ProfileMenu) BEFORE React hydrates so the * initial paint matches — no FOUC even when the server hasn't yet * baked the cookie-derived class. * * * * Cookie wins over matchMedia: 'system' (or absent) falls back to * the OS preference; 'light' / 'dark' are absolute. */ export const themeBootScript = (): string => ` (function(){ try { var rx = new RegExp('(?:^|;\\\\s*)${THEME_COOKIE.replace(/[.*+?^${}()|[\]\\]/g, '\\\\$&')}=([^;]*)'); var m = document.cookie.match(rx); var saved = m ? decodeURIComponent(m[1]) : ''; var dark = saved === 'dark' || (saved !== 'light' && window.matchMedia('(prefers-color-scheme: dark)').matches); document.documentElement.classList.toggle('dark', dark); } catch (_) { /* should be unreachable */ } })(); ` interface ThemeToggleProps extends HTMLAttributes