Files
Academia-Front/src/components/ui/Switch.tsx
T

144 lines
3.6 KiB
TypeScript

"use client";
import React from "react";
import {
Switch as HeroSwitch,
Label,
Description,
} from "@heroui/react";
export interface SwitchProps {
label?: React.ReactNode;
description?: string;
checked?: boolean;
onChange?: (checked: boolean) => void;
disabled?: boolean;
size?: "sm" | "md" | "lg";
checkedIcon?: React.ReactNode;
uncheckedIcon?: React.ReactNode;
id?: string;
name?: string;
className?: string;
}
const trackSizes = {
sm: "w-8 h-[18px]",
md: "w-11 h-6",
lg: "w-14 h-[30px]",
};
const thumbSizes = {
sm: "size-3.5",
md: "size-5",
lg: "size-[26px]",
};
const translateSizes = {
sm: "translate-x-3.5",
md: "translate-x-5",
lg: "translate-x-[26px]",
};
export const Switch: React.FC<SwitchProps> = ({
label,
description,
checked = false,
onChange,
disabled = false,
size = "md",
checkedIcon,
uncheckedIcon,
id,
name,
className = "",
}) => {
const switchId =
id ||
name ||
(typeof label === "string"
? label.toLowerCase().replace(/\s+/g, "-")
: undefined);
return (
<HeroSwitch
id={switchId}
name={name}
isSelected={checked}
isDisabled={disabled}
size={size}
className={className}
onChange={(e: any) => {
if (!onChange || disabled) return;
const val = typeof e === "boolean" ? e : Boolean(e?.target?.checked);
onChange(val);
}}
>
<HeroSwitch.Content>
<HeroSwitch.Control
className={`
${trackSizes[size]}
relative shrink-0 inline-flex items-center rounded-full p-0.5
transition-colors duration-200 ease-in-out cursor-pointer
border-0 m-0 box-border outline-none
${
checked
? "bg-cyan-500"
: "bg-slate-300 hover:bg-slate-400 dark:bg-slate-700 dark:hover:bg-slate-600"
}
${disabled ? "cursor-not-allowed opacity-50" : ""}
`}
>
<HeroSwitch.Thumb
className={`
${thumbSizes[size]}
${checked ? translateSizes[size] : "translate-x-0"}
border-0 m-0 pointer-events-none shrink-0 flex items-center justify-center
rounded-full bg-white text-slate-800 shadow-md
transition-transform duration-200 ease-in-out
`}
>
{(checkedIcon || uncheckedIcon) && (
<HeroSwitch.Icon>
{checked ? checkedIcon : uncheckedIcon}
</HeroSwitch.Icon>
)}
</HeroSwitch.Thumb>
</HeroSwitch.Control>
{/* TEXTOS */}
{(label || description) && (
<div className="flex flex-col text-left">
{label && (
<Label
className={`
text-xs sm:text-sm font-medium transition-colors cursor-pointer
${
disabled
? "text-slate-400 dark:text-slate-600 cursor-not-allowed"
: "text-slate-800 hover:text-slate-950 dark:text-slate-200 dark:hover:text-white"
}
`}
>
{label}
</Label>
)}
{description && (
<Description
className={`
text-xs text-slate-500 dark:text-slate-400 cursor-pointer
${disabled ? "cursor-not-allowed" : ""}
`}
>
{description}
</Description>
)}
</div>
)}
</HeroSwitch.Content>
</HeroSwitch>
);
};