SPB Git forge

spb/countryatlas

Public
20commits 1branches 0releases
268.3 MBsize
maindefault branch
12 days agolast push
TypeScript 57% Python 38.6% JavaScript 3.6% CSS 0.6%
1.8 KB · 42 lines tsx
Raw Blame History
1'use client';2import { Moon, Sun } from 'lucide-react';3import { useEffect, useState } from 'react';4import { t } from '@/i18n';56export const THEME_KEY = 'ca-theme';78/** Applied before first paint by the inline script in layout.tsx; here we only toggle and persist. */9export function ThemeToggle({ className }: { className?: string }) {10  const [dark, setDark] = useState<boolean | null>(null);11  useEffect(() => {12    setDark(document.documentElement.classList.contains('dark'));13    const mq = window.matchMedia('(prefers-color-scheme: dark)');14    const onChange = () => {15      if (!localStorage.getItem(THEME_KEY)) {16        document.documentElement.classList.toggle('dark', mq.matches);17        setDark(mq.matches);18      }19    };20    mq.addEventListener('change', onChange);21    return () => mq.removeEventListener('change', onChange);22  }, []);23  const toggle = () => {24    const next = !document.documentElement.classList.contains('dark');25    document.documentElement.classList.toggle('dark', next);26    try {27      localStorage.setItem(THEME_KEY, next ? 'dark' : 'light');28    } catch {29      /* private mode */30    }31    setDark(next);32  };33  return (34    <button type="button" onClick={toggle} className={`tap grid place-items-center rounded-sm text-ink-2 hover:bg-surface-2 hover:text-ink ${className ?? ''}`} aria-label={t('theme.toggle')} aria-pressed={dark ?? undefined} title={dark ? t('theme.light') : t('theme.dark')}>35      {dark ? <Sun size={18} aria-hidden /> : <Moon size={18} aria-hidden />}36    </button>37  );38}3940/** Inline bootstrap: apply stored/system theme before paint (no flash). */41export const THEME_BOOT = `try{var k='${THEME_KEY}',s=localStorage.getItem(k),d=s?s==='dark':matchMedia('(prefers-color-scheme: dark)').matches;if(d)document.documentElement.classList.add('dark')}catch(e){}`;42