الملفات
gracesalmoun/components/theme-toggle.tsx
2026-04-29 16:55:25 +03:00

79 أسطر
2.3 KiB
TypeScript

"use client";
import { useEffect, useState } from "react";
import type { Language } from "@/data/portfolio";
type Theme = "light" | "dark";
const STORAGE_KEY = "grace-portfolio-theme";
function applyTheme(theme: Theme) {
document.documentElement.dataset.theme = theme;
document.documentElement.style.colorScheme = theme;
}
export function ThemeToggle({ language }: { language: Language }) {
const [theme, setTheme] = useState<Theme>("light");
useEffect(() => {
const savedTheme = window.localStorage.getItem(STORAGE_KEY);
const nextTheme = savedTheme === "dark" ? "dark" : "light";
applyTheme(nextTheme);
setTheme(nextTheme);
}, []);
const nextTheme: Theme = theme === "dark" ? "light" : "dark";
const label =
language === "ar"
? theme === "dark"
? "\u062a\u0641\u0639\u064a\u0644 \u0627\u0644\u0648\u0636\u0639 \u0627\u0644\u0641\u0627\u062a\u062d"
: "\u062a\u0641\u0639\u064a\u0644 \u0627\u0644\u0648\u0636\u0639 \u0627\u0644\u062f\u0627\u0643\u0646"
: theme === "dark"
? "Switch to light mode"
: "Switch to dark mode";
function handleToggle() {
applyTheme(nextTheme);
window.localStorage.setItem(STORAGE_KEY, nextTheme);
setTheme(nextTheme);
}
return (
<button type="button" className="theme-toggle" onClick={handleToggle} aria-label={label} title={label}>
<span className="sr-only">{label}</span>
<svg
className="sun-icon"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
strokeWidth="1.8"
strokeLinecap="round"
strokeLinejoin="round"
aria-hidden="true"
>
<circle cx="12" cy="12" r="4" />
<path d="M12 2v2" />
<path d="M12 20v2" />
<path d="m4.93 4.93 1.41 1.41" />
<path d="m17.66 17.66 1.41 1.41" />
<path d="M2 12h2" />
<path d="M20 12h2" />
<path d="m6.34 17.66-1.41 1.41" />
<path d="m19.07 4.93-1.41 1.41" />
</svg>
<svg
className="moon-icon"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
strokeWidth="1.8"
strokeLinecap="round"
strokeLinejoin="round"
aria-hidden="true"
>
<path d="M20.8 14.7A8.5 8.5 0 0 1 9.3 3.2 8.5 8.5 0 1 0 20.8 14.7Z" />
</svg>
</button>
);
}