All components

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.

Open in the catalogue

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

/components/kokonutui/switch-button.tsx
"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>
  );
}

Similar components