50 lines
1.4 KiB
TypeScript
50 lines
1.4 KiB
TypeScript
import { useCallback, useEffect, useState } from "react";
|
|
import "./ThemeToggle.css";
|
|
import { saveSession } from "~/cookie";
|
|
import { ThemeTypes } from "~/types/theme";
|
|
import { Moon, Sun } from "lucide-react";
|
|
|
|
export const ThemeToggle = ({ theme: initialTheme }: { theme: ThemeTypes }) => {
|
|
const [theme, setTheme] = useState<ThemeTypes>(initialTheme);
|
|
|
|
useEffect(() => {
|
|
// Apply theme class to document body to match root.tsx
|
|
const body = document.body;
|
|
if (theme === "dark") {
|
|
body.classList.add("dark");
|
|
} else {
|
|
body.classList.remove("dark");
|
|
}
|
|
}, [theme]);
|
|
|
|
const changeTheme = useCallback(async () => {
|
|
const newTheme = theme === "light" ? "dark" : "light";
|
|
setTheme(newTheme);
|
|
|
|
// Update document body class immediately to match root.tsx
|
|
const body = document.body;
|
|
if (newTheme === "dark") {
|
|
body.classList.add("dark");
|
|
} else {
|
|
body.classList.remove("dark");
|
|
}
|
|
|
|
// Save to cookie for persistence
|
|
await saveSession("theme", newTheme);
|
|
}, [theme]);
|
|
|
|
return (
|
|
<button
|
|
onClick={changeTheme}
|
|
className="theme-toggle p-2 rounded-lg bg-WHITE2 hover:bg-GRAY3 transition-colors"
|
|
aria-label={`Switch to ${theme === "light" ? "dark" : "light"} theme`}
|
|
>
|
|
{theme === "light" ? (
|
|
<Moon className="w-5 h-5 text-BLACK2" />
|
|
) : (
|
|
<Sun className="w-5 h-5 text-GRAY2" />
|
|
)}
|
|
</button>
|
|
);
|
|
};
|