Swadhin Biswas feat(web): add repo insights, packages, releases, and review UIs · 3/6/2026
a4239f1
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
import { Monitor, Moon, Sun } from "lucide-react";
import { useEffect, useState } from "react";
type Theme = "light" | "dark" | "system";
function getStoredTheme(): Theme {
if (typeof window === "undefined") return "dark";
return (localStorage.getItem("theme") as Theme) || "system";
}
function resolveTheme(theme: Theme): "light" | "dark" {
if (theme === "system") {
return window.matchMedia("(prefers-color-scheme: dark)").matches
? "dark"
: "light";
}
return theme;
}
function applyTheme(theme: Theme) {
const resolved = resolveTheme(theme);
const html = document.documentElement;
if (resolved === "dark") {
html.classList.add("dark");
} else {
html.classList.remove("dark");
}
}
export function ThemeToggle() {
const [theme, setTheme] = useState<Theme>("dark"); // SSR default
useEffect(() => {
const stored = getStoredTheme();
setTheme(stored);
applyTheme(stored);
// Listen for system changes
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 cycleTheme = () => {
const order: Theme[] = ["light", "dark", "system"];
const idx = order.indexOf(theme);
const next = order[(idx + 1) % order.length];
setTheme(next);
localStorage.setItem("theme", next);
applyTheme(next);
};
const Icon = theme === "dark" ? Moon : theme === "light" ? Sun : Monitor;
const label =
theme === "dark" ? "Dark" : theme === "light" ? "Light" : "System";
return (
<button
onClick={cycleTheme}
className="inline-flex items-center gap-1.5 rounded-md px-2 py-1.5 text-sm text-muted-foreground hover:text-foreground hover:bg-accent transition-colors"
title={`Theme: ${label}. Click to cycle.`}
aria-label={`Current theme: ${label}`}
>
<Icon className="h-4 w-4" />
<span className="sr-only">{label}</span>
</button>
);
}
export default ThemeToggle;