import { useThemeStore, type ThemePref } from '../stores/themeStore'; import { SunIcon, MoonIcon, MonitorIcon } from './icons'; /** * 主题切换。 * * 两种形态共用一份状态: * - `compact`(侧栏 / 底部导航):单按钮,点一下翻转 * - 默认(「我的」页):三选一,因为 `system` 只有在能明确选中时才有意义 * * 单按钮不足以表达三态,但侧栏放不下三个选项;而只给单按钮的话 * 用户一旦点过就永久脱离了「跟随系统」—— 那是个回不去的单向门。 * 所以两个入口都提供,compact 用于快速切换,完整形态用于设定偏好。 */ const OPTIONS: { value: ThemePref; label: string; hint: string; Icon: (p: { className?: string }) => JSX.Element }[] = [ { value: 'light', label: '浅色', hint: '始终使用浅色', Icon: SunIcon }, { value: 'dark', label: '深色', hint: '始终使用深色', Icon: MoonIcon }, { value: 'system', label: '跟随系统', hint: '随系统的深浅色设置切换', Icon: MonitorIcon } ]; /** 侧栏用的单按钮:点一下在浅/深之间翻转。 */ export function ThemeToggleButton({ className = '' }: { className?: string }) { const resolved = useThemeStore(s => s.resolved); const pref = useThemeStore(s => s.pref); const toggle = useThemeStore(s => s.toggle); const dark = resolved === 'dark'; return ( ); } /** 「我的」页用的三选一。 */ export default function ThemePicker() { const pref = useThemeStore(s => s.pref); const resolved = useThemeStore(s => s.resolved); const setPref = useThemeStore(s => s.setPref); return (
「跟随系统」会随系统的深色开关自动切换,不选它就固定在一种外观。
{/* 分段控件而不是三个独立卡片。 三选一的语义是「三种互斥的偏好」,分段控件正好表达这个;独立卡片看起来 像可多选。选中态用整块底色(而非仅描边),在深色下也比描边更容易辨认。 */}