import { useState } from 'react'; import { type ThemePref, readStoredTheme, setThemePref } from '../../lib/theme'; const ICON_PROPS = { width: 14, height: 14, viewBox: '0 0 24 24', fill: 'none', stroke: 'currentColor', strokeWidth: 1.8, strokeLinecap: 'round' as const, strokeLinejoin: 'round' as const, 'aria-hidden': true, }; const OPTIONS: Array<{ value: ThemePref; label: string; icon: JSX.Element }> = [ { value: 'system', label: 'システム設定に合わせる', icon: ( ), }, { value: 'light', label: 'ライト', icon: ( ), }, { value: 'dark', label: 'ダーク', icon: ( ), }, ]; /** * Compact 3-way theme switch (system / light / dark) for the TopBar. * * All theme logic lives in lib/theme.ts: this only tracks the displayed * preference and calls setThemePref (persist + apply) on selection. The * pre-paint inline script in index.html + initTheme() keep the actual * [data-theme] attribute correct on load and on OS changes. */ export function ThemeToggle() { const [pref, setPref] = useState(() => readStoredTheme()); const choose = (value: ThemePref) => { setPref(value); setThemePref(value); }; return ( {OPTIONS.map((opt) => { const active = pref === opt.value; return ( choose(opt.value)} aria-label={opt.label} aria-pressed={active} title={opt.label} className={`flex items-center justify-center w-6 h-6 rounded transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent-ring ${ active ? 'bg-canvas text-slate-900 shadow-sm' : 'text-slate-500 hover:text-slate-800' }`} > {opt.icon} ); })} ); }