feat(settings): add theme preference selector replacing header ModeToggle

This commit is contained in:
2026-04-21 23:23:32 -04:00
parent 3e3c8056b1
commit 7f7c945396
2 changed files with 64 additions and 1 deletions

View File

@@ -1,7 +1,9 @@
"use client"; "use client";
import { Sparkles, Zap } from "lucide-react"; import { Monitor, Moon, Sparkles, Sun, Zap } from "lucide-react";
import { useTheme } from "next-themes";
import { Badge } from "@/components/ui/badge"; import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import { Checkbox } from "@/components/ui/checkbox"; import { Checkbox } from "@/components/ui/checkbox";
import { Label } from "@/components/ui/label"; import { Label } from "@/components/ui/label";
import { useIsMobile } from "@/hooks/use-mobile"; import { useIsMobile } from "@/hooks/use-mobile";
@@ -26,6 +28,7 @@ export function SettingsPanel({
settings, settings,
}: SettingsPanelProps) { }: SettingsPanelProps) {
const isMobile = useIsMobile(); const isMobile = useIsMobile();
const { setTheme, theme } = useTheme();
const valuePrefix = hasLoadedSettings const valuePrefix = hasLoadedSettings
? "Current preference" ? "Current preference"
: "Default value"; : "Default value";
@@ -156,6 +159,55 @@ export function SettingsPanel({
</div> </div>
</div> </div>
</div> </div>
<div className={settingRowClasses}>
<div className="flex items-start gap-3">
<div className="mt-0.5 rounded-full bg-primary/10 p-2 text-primary">
<Sun className="h-4 w-4" />
</div>
<div className="min-w-0 flex-1 space-y-3">
<div className="space-y-1">
<p className="text-sm font-medium text-foreground">
Theme preference
</p>
<p className="text-sm leading-relaxed text-muted-foreground">
Choose the appearance LocalCal should use on this device.
</p>
</div>
<div
className={cn(
"grid gap-2",
isMobile ? "grid-cols-1" : "grid-cols-3",
)}
>
<Button
type="button"
variant={theme === "light" ? "default" : "outline"}
onClick={() => setTheme("light")}
>
<Sun className="h-4 w-4" />
Light
</Button>
<Button
type="button"
variant={theme === "dark" ? "default" : "outline"}
onClick={() => setTheme("dark")}
>
<Moon className="h-4 w-4" />
Dark
</Button>
<Button
type="button"
variant={theme === "system" ? "default" : "outline"}
onClick={() => setTheme("system")}
>
<Monitor className="h-4 w-4" />
System
</Button>
</div>
</div>
</div>
</div>
</div> </div>
<div className={cn(settingRowClasses, "space-y-3")}> <div className={cn(settingRowClasses, "space-y-3")}>

View File

@@ -0,0 +1,11 @@
import { describe, expect, test } from "bun:test";
import { readFileSync } from "node:fs";
describe("settings panel", () => {
test("theme controls are available from settings after leaving the mobile header", () => {
const source = readFileSync("src/components/settings-panel.tsx", "utf8");
expect(source).toContain("Theme preference");
expect(source).toContain("setTheme(");
});
});