Toggle Switch Button
Toggle Switch Button is a React and Tailwind CSS button component from Kokonut UI, licensed MIT. Copy it and paste it into your project.
Kokonut UI
MIT
buttons
What it is
Toggle Switch Button is a React and Tailwind CSS button component from Kokonut UI, licensed MIT. Copy it and paste it into your project.
How to use it
Open it in the catalogue, press copy, and paste it into your project. The prompt you copy carries the code and the rules that tell your agent to reproduce it without changing anything.
Five free copies a month. No card.
Needs
npm i lucide-react
Licence
This component comes from Kokonut UI and is redistributed under the MIT licence, which permits commercial use. The copyright notice travels with the code.
Toggle Switch Button
"use client";
/**
* @author: @dorianbaffier
* @description: Switch Button
* @version: 1.0.0
* @date: 2025-06-26
* @license: MIT
* @website: https://kokonutui.com
* @github: https://github.com/kokonut-labs/kokonutui
*/
import { Sun } from "lucide-react";
import { useTheme } from "next-themes";
import { Button } from "@/components/ui/button";
import { cn } from "@/lib/utils";
interface SwitchButtonProps
extends React.ButtonHTMLAttributes<HTMLButtonElement> {
variant?: "minimal";
size?: "sm" | "default" | "lg";
showLabel?: boolean;
}
export default function SwitchButton({
className,
variant = "minimal",
size = "default",
showLabel = true,
...props
}: SwitchButtonProps) {
const { setTheme, theme } = useTheme();
const handleThemeToggle = () => {
setTheme(theme === "dark" ? "light" : "dark");
};
const variants = {
minimal: [
"rounded-lg",
"bg-gradient-to-b from-zinc-50/95 to-zinc-100/95 dark:from-zinc-800/95 dark:to-zinc-900/95",
"hover:from-zinc-100/95 hover:to-zinc-200/95 dark:hover:from-zinc-700/95 dark:hover:to-zinc-800/95",
"border border-zinc-200 dark:border-zinc-700/80",
"hover:border-zinc-300 dark:hover:border-zinc-600",
"shadow-[0_1px_2px_-1px_rgb(0_0_0/0.1),0_1px_3px_-2px_rgb(0_0_0/0.1)] dark:shadow-[0_1px_2px_-1px_rgb(0_0_0/0.3),0_1px_3px_-2px_rgb(0_0_0/0.3)]",
"hover:shadow-[0_2px_4px_-2px_rgb(0_0_0/0.15),0_2px_6px_-3px_rgb(0_0_0/0.15)] dark:hover:shadow-[0_2px_4px_-2px_rgb(0_0_0/0.4),0_2px_6px_-3px_rgb(0_0_0/0.4)]",
"active:shadow-[0_0px_1px_0_rgb(0_0_0/0.1)] dark:active:shadow-[0_0px_1px_0_rgb(0_0_0/0.2)]",
"transition-all duration-200 ease-out",
"backdrop-blur-sm",
"relative",
"after:absolute after:inset-0 after:rounded-lg after:bg-gradient-to-t after:from-white/10 after:to-transparent after:opacity-0 hover:after:opacity-100 after:transition-opacity",
"before:absolute before:inset-[1px] before:rounded-[7px] before:bg-gradient-to-b before:from-white/20 before:to-transparent before:opacity-0 hover:before:opacity-100 before:transition-opacity dark:before:from-white/5",
],
};
const sizes = {
sm: "h-8 px-3 text-sm",
default: "h-10 px-4",
lg: "h-11 px-5",
};
return (
<Button
className={cn(
"group relative",
"transition-all duration-300 ease-out",
"text-zinc-600 dark:text-zinc-300",
"hover:text-zinc-800 dark:hover:text-zinc-100",
variants[variant],
sizes[size],
className
)}
onClick={handleThemeToggle}
{...props}
>
<div
className={cn(
"flex items-center gap-2",
"transition-all duration-300 ease-out"
)}
>
<Sun
className={cn(
"transition-all duration-700 ease-in-out",
size === "sm" && "h-3.5 w-3.5",
size === "default" && "h-4 w-4",
size === "lg" && "h-5 w-5",
"group-hover:rotate-[360deg] group-hover:scale-110",
theme === "dark" ? "rotate-180" : "rotate-0",
"transform-gpu",
"drop-shadow-[0_0_12px_rgba(252,211,77,0.3)] dark:drop-shadow-[0_0_12px_rgba(252,211,77,0.2)]",
theme === "dark"
? "text-zinc-300 group-hover:text-zinc-100"
: "text-amber-500 group-hover:text-amber-600",
"group-active:scale-95"
)}
/>
{showLabel && (
<span
className={cn(
"relative font-medium capitalize",
"transition-opacity duration-300 ease-out"
)}
>
<span
className={cn(
"absolute inset-0",
theme === "dark" ? "opacity-0" : "opacity-100",
"transition-opacity duration-300 ease-out"
)}
>
Light
<span
className={cn(
"absolute -bottom-px left-0 h-px w-full",
"bg-linear-to-r from-zinc-400/0 via-zinc-400/50 to-zinc-400/0",
"dark:from-zinc-600/0 dark:via-zinc-600/50 dark:to-zinc-600/0",
"opacity-0 group-hover:opacity-100",
"transition-opacity duration-200"
)}
/>
</span>
<span
className={cn(
"absolute inset-0",
theme === "dark" ? "opacity-100" : "opacity-0",
"transition-opacity duration-300 ease-out"
)}
>
Dark
<span
className={cn(
"absolute -bottom-px left-0 h-px w-full",
"bg-linear-to-r from-zinc-400/0 via-zinc-400/50 to-zinc-400/0",
"dark:from-zinc-600/0 dark:via-zinc-600/50 dark:to-zinc-600/0",
"opacity-0 group-hover:opacity-100",
"transition-opacity duration-200"
)}
/>
</span>
<span className="opacity-0">Light</span>
</span>
)}
</div>
<span
className={cn(
"absolute inset-0",
"bg-gradient-to-r from-zinc-500/0 via-zinc-500/[0.12] to-zinc-500/0 dark:from-white/0 dark:via-white/[0.05]",
"translate-x-[-100%]",
"group-hover:translate-x-[100%]",
"transition-transform duration-500",
"ease-in-out",
"pointer-events-none",
"z-[1]"
)}
/>
<span
className={cn(
"absolute inset-0 opacity-0 group-hover:opacity-100",
"bg-[radial-gradient(circle_at_50%_50%,rgba(255,255,255,0.12),transparent_70%)] dark:bg-[radial-gradient(circle_at_50%_50%,rgba(255,255,255,0.07),transparent_70%)]",
"transition-opacity duration-500",
"pointer-events-none",
"z-[2]"
)}
/>
</Button>
);
}