lightswind
Version:
A collection of beautifully crafted React Components, Blocks & Templates for Modern Developers. Create stunning web applications effortlessly by using our 160+ professional and animated react components.
63 lines (62 loc) • 5.18 kB
JavaScript
// @ts-nocheck
"use client";
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import { useState, useEffect } from "react";
import { motion } from "framer-motion";
import { Sun, Moon, Cloud, Star } from "lucide-react";
import { cn } from "../../lib/utils";
export function CoolThemeToggle({ className, size = "md" }) {
const [theme, setTheme] = useState("light");
const [mounted, setMounted] = useState(false);
useEffect(() => {
setMounted(true);
const isDark = document.documentElement.classList.contains("dark");
setTheme(isDark ? "dark" : "light");
const observer = new MutationObserver(() => {
setTheme(document.documentElement.classList.contains("dark") ? "dark" : "light");
});
observer.observe(document.documentElement, { attributes: true, attributeFilter: ["class"] });
return () => observer.disconnect();
}, []);
const toggleTheme = () => {
const newTheme = theme === "light" ? "dark" : "light";
setTheme(newTheme);
if (newTheme === "dark") {
document.documentElement.classList.add("dark");
localStorage.setItem("theme", "dark");
}
else {
document.documentElement.classList.remove("dark");
localStorage.setItem("theme", "light");
}
};
if (!mounted)
return _jsx("div", { className: cn("inline-flex rounded-full bg-muted", size === "sm" ? "h-6 w-12" : size === "md" ? "h-8 w-16" : "h-10 w-20") });
const sizes = {
sm: { button: "w-12 h-6", thumb: "w-4 h-4", icon: "w-2.5 h-2.5", padding: "p-1", translateX: "translateX(24px)", cloudSize: "w-3 h-3" },
md: { button: "w-16 h-8", thumb: "w-6 h-6", icon: "w-4 h-4", padding: "p-1", translateX: "translateX(32px)", cloudSize: "w-5 h-5" },
lg: { button: "w-20 h-10", thumb: "w-8 h-8", icon: "w-5 h-5", padding: "p-1", translateX: "translateX(40px)", cloudSize: "w-6 h-6" }
};
const currentSize = sizes[size];
return (_jsxs("button", { onClick: toggleTheme, className: cn("relative rounded-full transition-colors duration-500 ease-in-out focus:outline-none focus-visible:ring-2 focus-visible:ring-primary focus-visible:ring-offset-2 overflow-hidden", theme === "dark" ? "bg-slate-900" : "bg-sky-300", currentSize.button, currentSize.padding, className), "aria-label": "Toggle theme", children: [_jsxs("div", { className: "absolute inset-0 z-0 overflow-hidden rounded-full", children: [_jsx(motion.div, { initial: false, animate: {
opacity: theme === "light" ? 1 : 0,
y: theme === "light" ? 0 : 10,
}, transition: { duration: 0.4 }, className: "absolute inset-0 flex items-center justify-end pr-2 text-white", children: _jsx(Cloud, { className: cn("text-white/80 fill-white/80", currentSize.cloudSize) }) }), _jsx(motion.div, { initial: false, animate: {
opacity: theme === "dark" ? 1 : 0,
y: theme === "dark" ? 0 : -10,
}, transition: { duration: 0.4 }, className: "absolute inset-0 flex items-center justify-start pl-2", children: _jsxs("div", { className: "relative w-full h-full", children: [_jsx(Star, { className: cn("absolute top-1 left-2 text-yellow-100 fill-yellow-100 opacity-70", size === "lg" ? "w-2 h-2" : "w-1 h-1") }), _jsx(Star, { className: cn("absolute bottom-2 left-4 text-yellow-100 fill-yellow-100 opacity-50", size === "lg" ? "w-3 h-3" : "w-1.5 h-1.5") }), _jsx(Star, { className: cn("absolute top-3 left-6 text-yellow-100 fill-yellow-100 opacity-90", size === "lg" ? "w-1.5 h-1.5" : "w-1 h-1") })] }) })] }), _jsx(motion.div, { layout: true, transition: {
type: "spring",
stiffness: 500,
damping: 30,
}, className: cn("relative z-10 flex items-center justify-center rounded-full shadow-md", theme === "dark" ? "bg-slate-800" : "bg-yellow-400", currentSize.thumb), animate: {
x: theme === "dark" ? parseInt(currentSize.translateX.replace("translateX(", "").replace("px)", "")) : 0
}, children: _jsxs("div", { className: "relative flex items-center justify-center w-full h-full", children: [_jsx(motion.div, { initial: false, animate: {
rotate: theme === "dark" ? 180 : 0,
scale: theme === "dark" ? 0 : 1,
opacity: theme === "dark" ? 0 : 1,
}, transition: { duration: 0.4 }, className: "absolute", children: _jsx(Sun, { className: cn("text-white fill-white/20", currentSize.icon) }) }), _jsx(motion.div, { initial: false, animate: {
rotate: theme === "dark" ? 0 : -180,
scale: theme === "dark" ? 1 : 0,
opacity: theme === "dark" ? 1 : 0,
}, transition: { duration: 0.4 }, className: "absolute flex items-center justify-center", children: _jsx(Moon, { className: cn("text-yellow-200 fill-yellow-200", currentSize.icon) }) })] }) })] }));
}