36 lines
1.3 KiB
TypeScript
36 lines
1.3 KiB
TypeScript
"use client";
|
|
|
|
import { useTheme } from "next-themes";
|
|
import { useEffect, useState } from "react";
|
|
|
|
export function ThemeToggle() {
|
|
const { resolvedTheme, setTheme } = useTheme();
|
|
const [mounted, setMounted] = useState(false);
|
|
|
|
useEffect(() => setMounted(true), []);
|
|
|
|
if (!mounted) return <div className="h-9 w-9" />;
|
|
|
|
const isDark = resolvedTheme === "dark";
|
|
|
|
return (
|
|
<button
|
|
onClick={() => setTheme(isDark ? "light" : "dark")}
|
|
className="flex h-9 w-9 items-center justify-center border border-[var(--color-border-strong)] bg-[var(--color-bg-elevated)] text-[var(--color-text-primary)] transition-colors hover:bg-[var(--color-bg-elevated-hover)]"
|
|
aria-label={`Switch to ${isDark ? "light" : "dark"} mode`}
|
|
title={`Switch to ${isDark ? "light" : "dark"} mode`}
|
|
>
|
|
{isDark ? (
|
|
<svg className="h-[18px] w-[18px]" fill="none" stroke="currentColor" strokeWidth="2" viewBox="0 0 24 24">
|
|
<circle cx="12" cy="12" r="5" />
|
|
<path d="M12 1v2M12 21v2M4.22 4.22l1.42 1.42M18.36 18.36l1.42 1.42M1 12h2M21 12h2M4.22 19.78l1.42-1.42M18.36 5.64l1.42-1.42" />
|
|
</svg>
|
|
) : (
|
|
<svg className="h-[18px] w-[18px]" fill="none" stroke="currentColor" strokeWidth="2" viewBox="0 0 24 24">
|
|
<path d="M21 12.79A9 9 0 1111.21 3 7 7 0 0021 12.79z" />
|
|
</svg>
|
|
)}
|
|
</button>
|
|
);
|
|
}
|