41 lines · 1.3 KBRaw
src/components/ThemeToggle.tsx | 17 +++++++++++++++++
src/theme.ts | 8 +++++---
2 files changed, 22 insertions(+), 3 deletions(-)
diff --git a/src/components/ThemeToggle.tsx b/src/components/ThemeToggle.tsx
new file mode 100644
index 0000000..8a438fe
--- /dev/null
+++ b/src/components/ThemeToggle.tsx
@@ -0,0 +1,17 @@
+export function ThemeToggle() {
+ const [pick, setPick] = useState<ThemeName | null>(() => localStorage.getItem("theme") as ThemeName | null);
+
+ useEffect(() => {
+ if (pick) document.documentElement.dataset.theme = pick;
+ else delete document.documentElement.dataset.theme; // follow the system
+ }, [pick]);
+
+ function toggle() {
+ const dark = pick ? pick === "dark" : matchMedia("(prefers-color-scheme: dark)").matches;
+ const next = dark ? "light" : "dark";
+ localStorage.setItem("theme", next);
+ setPick(next);
+ }
+
+ return <button onClick={toggle} aria-label="Toggle dark mode">◐</button>;
+}
diff --git a/src/theme.ts b/src/theme.ts
index 6823096..8203cf9 100644
--- a/src/theme.ts
+++ b/src/theme.ts
@@ -1,4 +1,6 @@
-export const theme = {
- bg: "#ffffff",
- text: "#111111",
+export const themes = {
+ light: { bg: "#ffffff", text: "#111111" },
+ dark: { bg: "#0d1117", text: "#e6edf3" },
};
+
+export type ThemeName = keyof typeof themes;