55 lines
1.8 KiB
TypeScript
55 lines
1.8 KiB
TypeScript
import IconButton from '@mui/material/IconButton';
|
|
import Menu from '@mui/material/Menu';
|
|
import MenuItem from '@mui/material/MenuItem';
|
|
import ListItemIcon from '@mui/material/ListItemIcon';
|
|
import ListItemText from '@mui/material/ListItemText';
|
|
import LightModeIcon from '@mui/icons-material/LightMode';
|
|
import DarkModeIcon from '@mui/icons-material/DarkMode';
|
|
import SettingsBrightnessIcon from '@mui/icons-material/SettingsBrightness';
|
|
import { useState } from 'react';
|
|
import { useThemeStore } from '@/store';
|
|
import type { ThemeMode } from '@/theme';
|
|
|
|
const modes: { value: ThemeMode; label: string; icon: React.ReactNode }[] = [
|
|
{ value: 'light', label: 'Light', icon: <LightModeIcon fontSize="small" /> },
|
|
{ value: 'dark', label: 'Dark', icon: <DarkModeIcon fontSize="small" /> },
|
|
{ value: 'system', label: 'System', icon: <SettingsBrightnessIcon fontSize="small" /> },
|
|
];
|
|
|
|
export function ThemeToggle() {
|
|
const { mode, setMode } = useThemeStore();
|
|
const [anchor, setAnchor] = useState<null | HTMLElement>(null);
|
|
|
|
const current = modes.find((m) => m.value === mode) ?? modes[2]!;
|
|
|
|
return (
|
|
<>
|
|
<IconButton
|
|
onClick={(e) => setAnchor(e.currentTarget)}
|
|
aria-label="Toggle theme"
|
|
size="small"
|
|
sx={{ color: 'text.primary' }}
|
|
>
|
|
{current.icon}
|
|
</IconButton>
|
|
<Menu anchorEl={anchor} open={Boolean(anchor)} onClose={() => setAnchor(null)}>
|
|
{modes.map((m) => (
|
|
<MenuItem
|
|
key={m.value}
|
|
selected={mode === m.value}
|
|
onClick={() => {
|
|
setMode(m.value);
|
|
setAnchor(null);
|
|
}}
|
|
>
|
|
<ListItemIcon>{m.icon}</ListItemIcon>
|
|
<ListItemText>{m.label}</ListItemText>
|
|
</MenuItem>
|
|
))}
|
|
</Menu>
|
|
</>
|
|
);
|
|
}
|
|
|
|
export default ThemeToggle;
|