JustAPI Bot fix: resolve ThemeToggle merge conflict markers · 7/14/2026
f589e00
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
"use client";
import { Monitor, Moon, Sun, Palette } from "lucide-react";
import { useEffect, useState } from "react";
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu";
type Theme = "light" | "dark" | "system" | "github-dark" | "dracula" | "rose-pine" | "tokyo-night";
function getStoredTheme(): Theme {
if (typeof window === "undefined") return "dark";
return (localStorage.getItem("theme") as Theme) || "system";
}
function applyTheme(theme: Theme) {
const html = document.documentElement;
const isSystemDark = window.matchMedia("(prefers-color-scheme: dark)").matches;
const activeTheme: string = theme === "system" ? (isSystemDark ? "dark" : "light") : theme;
if (activeTheme === "light") {
html.classList.remove("dark");
html.removeAttribute("data-theme");
} else {
html.classList.add("dark");
if (activeTheme !== "dark" && activeTheme !== "system") {
html.setAttribute("data-theme", activeTheme);
} else {
html.removeAttribute("data-theme");
}
}
}
export function ThemeToggle() {
const [theme, setTheme] = useState<Theme>("dark");
useEffect(() => {
const stored = getStoredTheme();
setTheme(stored);
applyTheme(stored);
const mq = window.matchMedia("(prefers-color-scheme: dark)");
const handler = () => {
if (getStoredTheme() === "system") {
applyTheme("system");
}
};
mq.addEventListener("change", handler);
return () => mq.removeEventListener("change", handler);
}, []);
const changeTheme = (newTheme: Theme) => {
setTheme(newTheme);
localStorage.setItem("theme", newTheme);
applyTheme(newTheme);
};
return (
<DropdownMenu>
<DropdownMenuTrigger asChild>
<button
className="inline-flex items-center justify-center h-9 w-9 rounded-full border border-border/50 bg-background transition-all hover:bg-accent hover:text-accent-foreground focus:outline-none focus:ring-2 focus:ring-primary/20"
aria-label="Toggle theme"
>
<Palette className="h-4 w-4" />
<span className="sr-only">Toggle theme</span>
</button>
</DropdownMenuTrigger>
<DropdownMenuContent align="end" className="w-48 bg-popover border-border/50 backdrop-blur-xl">
<DropdownMenuItem onClick={() => changeTheme("light")} className="cursor-pointer">
<Sun className="mr-2 h-4 w-4" />
<span>Light</span>
</DropdownMenuItem>
<DropdownMenuItem onClick={() => changeTheme("dark")} className="cursor-pointer">
<Moon className="mr-2 h-4 w-4" />
<span>Default Dark</span>
</DropdownMenuItem>
<DropdownMenuItem onClick={() => changeTheme("github-dark")} className="cursor-pointer">
<span className="mr-2 h-4 w-4 rounded-full bg-card border border-border/80"></span>
<span>GitHub Dark</span>
</DropdownMenuItem>
<DropdownMenuItem onClick={() => changeTheme("dracula")} className="cursor-pointer">
<span className="mr-2 h-4 w-4 rounded-full bg-[#282a36] border border-border/80"></span>
<span>Dracula</span>
</DropdownMenuItem>
<DropdownMenuItem onClick={() => changeTheme("rose-pine")} className="cursor-pointer">
<span className="mr-2 h-4 w-4 rounded-full bg-[#191724] border border-border/80"></span>
<span>Rosé Pine</span>
</DropdownMenuItem>
<DropdownMenuItem onClick={() => changeTheme("tokyo-night")} className="cursor-pointer">
<span className="mr-2 h-4 w-4 rounded-full bg-[#1a1b26] border border-border/80"></span>
<span>Tokyo Night</span>
</DropdownMenuItem>
<DropdownMenuItem onClick={() => changeTheme("system")} className="cursor-pointer border-t mt-1 pt-1">
<Monitor className="mr-2 h-4 w-4" />
<span>System</span>
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
);
}
export default ThemeToggle;