This document outlines the steps to create Switch
component styled withTailwind CSS and using some npm dependency libraries.
Node.js
and npm
installed on your machine.Tailwind CSS
installed in your project.CVA(class-variance-authority)
is a utility for managing CSS class names based on various conditions.clsx
is a tiny utility for constructing className strings conditionally.1// switch.helpers.ts
2import { cva } from "class-variance-authority";
3
4export const switchVariants = cva(
5 "rounded-full cursor-pointer transition-all duration-150 bg-neutral-400 data-[disabled=true]:bg-neutral-300",
6 {
7 variants: {
8 size: {
9 small: "w-7 h-4 p-0.5",
10 medium: "w-10 h-6 p-1",
11 large: "w-12 h-7 p-1",
12 },
13 color: {
14 primary:
15 "data-[checked=true]:bg-blue-500 data-[checked=true]:data-[disabled=true]:bg-blue-300",
16 secondary:
17 "data-[checked=true]:bg-gray-500 data-[checked=true]:data-[disabled=true]:bg-gray-300",
18 success:
19 "data-[checked=true]:bg-green-500 data-[checked=true]:data-[disabled=true]:bg-green-300",
20 danger:
21 "data-[checked=true]:bg-red-500 data-[checked=true]:data-[disabled=true]:bg-red-300",
22 warning:
23 "data-[checked=true]:bg-yellow-500 data-[checked=true]:data-[disabled=true]:bg-yellow-300",
24 info: "data-[checked=true]:bg-cyan-500 data-[checked=true]:data-[disabled=true]:bg-cyan-300",
25 light:
26 "data-[checked=true]:bg-gray-300 data-[checked=true]:data-[disabled=true]:bg-gray-200",
27 dark: "data-[checked=true]:bg-black data-[checked=true]:data-[disabled=true]:bg-gray-400",
28 },
29 },
30 defaultVariants: {
31 size: "medium",
32 color: "primary",
33 },
34 },
35);
36
37export const switchIconVariants = cva(
38 "rounded-full bg-white transform transition-all duration-150 translate-x-0",
39 {
40 variants: {
41 size: {
42 small: "w-3 h-3 data-[checked=true]:translate-x-3",
43 medium: "w-4 h-4 data-[checked=true]:translate-x-4",
44 large: "w-5 h-5 data-[checked=true]:translate-x-5",
45 },
46 },
47 defaultVariants: {
48 size: "medium",
49 },
50 },
51);
52
1// switch.component.tsx
2import clsx from "clsx";
3import type { VariantProps } from "class-variance-authority";
4import { switchIconVariants, switchVariants } from "./switch.helpers";
5
6export interface SwitchProps extends VariantProps<typeof switchVariants> {
7 checked: boolean;
8 disabled?: boolean;
9 className?: string;
10 onChange: (checked: boolean) => void;
11}
12
13const Switch: React.FC<SwitchProps> = ({
14 checked,
15 size,
16 color,
17 disabled,
18 className,
19 onChange,
20}) => {
21 const handleClick = () => {
22 if (disabled) return;
23 onChange(!checked);
24 };
25
26 return (
27 <div
28 data-disabled={Boolean(disabled).toString()}
29 data-checked={Boolean(checked).toString()}
30 className={clsx(switchVariants({ size, color }), className)}
31 onClick={handleClick}
32 >
33 <div
34 data-checked={Boolean(checked).toString()}
35 className={switchIconVariants({ size })}
36 />
37 </div>
38 );
39};
40
41export default Switch;
42