feat(settings): Add Light/Dark mode toggle, rename SETTING to SETTINGS

- Change menu name from SETTING to SETTINGS
- Add themeStore with light/dark mode persistence
- Add Light/Dark toggle in Display Settings
- Apply theme to app root
This commit is contained in:
2026-03-13 14:15:42 +08:00
parent 2ce90ec450
commit 50daf52de6
4 changed files with 55 additions and 3 deletions

View File

@@ -3,20 +3,27 @@ import { router } from "./routes";
import { useDisplayMode } from "./hooks/useDisplayMode";
import { useSensorPolling } from "./hooks/useSensorPolling";
import { useEffect } from "react";
import { useThemeStore } from "./stores/themeStore";
function AppContent() {
const displayMode = useDisplayMode();
const { start, stop } = useSensorPolling({ enabled: true });
const theme = useThemeStore((state) => state.theme);
useEffect(() => {
start();
return () => stop();
}, [start, stop]);
useEffect(() => {
document.documentElement.classList.remove('light', 'dark');
document.documentElement.classList.add(theme);
}, [theme]);
return (
<div
data-display-mode={displayMode}
className={displayMode === 'remote' ? 'display-mode-remote' : 'display-mode-kiosk'}
className={`${theme === 'dark' ? 'dark' : 'light'} ${displayMode === 'remote' ? 'display-mode-remote' : 'display-mode-kiosk'}`}
>
<RouterProvider router={router} />
</div>

View File

@@ -75,7 +75,7 @@ const menuItems: MenuItem[] = [
},
{
id: "setting",
label: "SETTING",
label: "SETTINGS",
icon: <Settings className="w-5 h-5" />,
path: "/setting",
},

View File

@@ -2,9 +2,12 @@ import { Card, CardContent, CardHeader, CardTitle } from "../ui/card";
import { Button } from "../ui/button";
import { Switch } from "../ui/switch";
import { Label } from "../ui/label";
import { Settings } from "lucide-react";
import { Settings, Sun, Moon } from "lucide-react";
import { useThemeStore } from "../../stores/themeStore";
export function SettingView() {
const { theme, toggleTheme } = useThemeStore();
return (
<div className="space-y-4">
<div className="flex items-center gap-3">
@@ -17,6 +20,25 @@ export function SettingView() {
<CardTitle className="text-white">Display Settings</CardTitle>
</CardHeader>
<CardContent className="space-y-3">
{/* Light/Dark Mode */}
<div className="flex items-center justify-between p-3 bg-gray-800 rounded">
<div className="flex items-center gap-3">
{theme === 'dark' ? (
<Moon className="w-5 h-5 text-yellow-400" />
) : (
<Sun className="w-5 h-5 text-orange-400" />
)}
<Label htmlFor="theme-toggle" className="text-gray-300">
{theme === 'dark' ? 'Dark Mode' : 'Light Mode'}
</Label>
</div>
<Switch
id="theme-toggle"
checked={theme === 'dark'}
onCheckedChange={toggleTheme}
/>
</div>
<div className="flex items-center justify-between p-3 bg-gray-800 rounded">
<Label htmlFor="auto-brightness" className="text-gray-300">Auto Brightness</Label>
<Switch id="auto-brightness" defaultChecked />

View File

@@ -0,0 +1,23 @@
import { create } from 'zustand';
import { persist } from 'zustand/middleware';
type Theme = 'light' | 'dark';
interface ThemeState {
theme: Theme;
setTheme: (theme: Theme) => void;
toggleTheme: () => void;
}
export const useThemeStore = create<ThemeState>()(
persist(
(set) => ({
theme: 'dark',
setTheme: (theme) => set({ theme }),
toggleTheme: () => set((state) => ({ theme: state.theme === 'dark' ? 'light' : 'dark' })),
}),
{
name: 'theme-storage',
}
)
);