Switch
A toggle switch component.
Known Bug: This Switch component is tightly coupled with the dark mode switch. Need to extract mode switching logic from it and keep it pure.
Installations
Install radix-ui, clsx, and tailwind-merge to use avatar component.
npm install radix-ui clsx tailwind-merge
Add the following function in lib/utils
import clsx, { type ClassValue } from "clsx";
import { twMerge } from "tailwind-merge";
export function cx(...args: ClassValue[]) {
return twMerge(clsx(...args));
}
Copy paste the component
"use client";
import React, { useEffect, useState } from "react";
import { Switch as SwitchPrimitive } from "radix-ui";
import { cx } from "@/lib/utils";
const SwitchRoot = React.forwardRef<
React.ElementRef<typeof SwitchPrimitive.Root>,
React.ComponentPropsWithoutRef<typeof SwitchPrimitive.Root>
>(({ className, children, ...props }, forwardedRef) => {
const [isDark, setIsDark] = useState(false);
useEffect(() => {
if (localStorage.getItem("mode") === "dark") {
setIsDark(true);
}
}, []);
return (
<SwitchPrimitive.Root
ref={forwardedRef}
className={cx(
// base
"w-8 h-4 bg-gray-200 border border-gray-600 rounded-4xl relative flex items-center justify-start cursor-pointer",
// checked
"data-[state=checked]:bg-blue-200",
// className prop
className
)}
checked={isDark}
autoFocus={false}
onCheckedChange={(checked) => {
setIsDark(checked);
if (checked) {
localStorage.setItem("mode", "dark");
document.documentElement.classList.add("dark");
} else {
localStorage.setItem("mode", "light");
document.documentElement.classList.remove("dark");
}
}}
{...props}
>
{children}
</SwitchPrimitive.Root>
);
});
SwitchRoot.displayName = "SwitchRoot";
const SwitchThumb = React.forwardRef<
React.ElementRef<typeof SwitchPrimitive.Thumb>,
React.ComponentPropsWithoutRef<typeof SwitchPrimitive.Thumb>
>(({ className, ...props }, forwardedRef) => {
return (
<SwitchPrimitive.Thumb
ref={forwardedRef}
className={cx(
// base
"block w-4 h-4 bg-white border border-gray-600 rounded-full",
// transition and color
"data-[state=checked]:translate-x-4 data-[state=checked]:bg-blue-600",
// className prop
className
)}
{...props}
/>
);
});
SwitchThumb.displayName = "SwitchThumb";
export { SwitchRoot, SwitchThumb };
Usage
import { SwitchRoot, SwitchThumb } from "@/library/components/ui/switch";
export default function Switch() {
return (
<CardRoot>
<SwitchRoot>
<SwitchThumb></SwitchThumb>
</SwitchRoot>
</CardRoot>
);
}
Next: Table
Found a bug? Report here.