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

149 lines
3.8 KiB
TypeScript

"use client";
import React from "react";
import {
Checkbox as HeroUICheckbox,
Description,
FieldError,
} from "@heroui/react";
import { FiCheck, FiMinus } from "react-icons/fi";
export interface CheckboxProps
extends Omit<
React.ComponentProps<typeof HeroUICheckbox>,
"children" | "defaultSelected" | "isDisabled" | "isInvalid" | "isIndeterminate"
> {
label?: React.ReactNode;
description?: string;
errorMessage?: string;
checked?: boolean;
disabled?: boolean;
indeterminate?: boolean;
className?: string;
}
export const Checkbox = ({
label,
description,
errorMessage,
indeterminate = false,
checked,
isSelected,
disabled = false,
className = "",
id,
name,
onChange,
...props
}: CheckboxProps) => {
return (
<HeroUICheckbox
{...props}
id={id}
name={name}
isSelected={checked}
isDisabled={disabled}
isIndeterminate={indeterminate}
isInvalid={Boolean(errorMessage)}
onChange={onChange}
className={className}
>
<HeroUICheckbox.Content className="items-start gap-2.5">
<HeroUICheckbox.Control
className={[
"mt-0.5 shrink-0 size-4 rounded-md",
"border",
"transition-all duration-200",
// Estado normal
"bg-white dark:bg-slate-900",
"border-slate-300 dark:border-slate-700",
// Hover
"group-hover:border-slate-400",
"dark:group-hover:border-slate-500",
// Focus
"data-[focus-visible=true]:ring-2",
"data-[focus-visible=true]:ring-cyan-500",
"data-[focus-visible=true]:ring-offset-2",
"data-[focus-visible=true]:ring-offset-white",
"dark:data-[focus-visible=true]:ring-offset-slate-950",
// Seleccionado
"data-[selected=true]:bg-cyan-500",
"data-[selected=true]:border-cyan-500",
"data-[selected=true]:text-slate-950",
"data-[selected=true]:shadow-sm",
"data-[selected=true]:shadow-cyan-500/20",
// Indeterminado
"data-[indeterminate=true]:bg-cyan-500",
"data-[indeterminate=true]:border-cyan-500",
"data-[indeterminate=true]:text-slate-950",
// Error
errorMessage
? "data-[invalid=true]:border-rose-500"
: "",
]
.filter(Boolean)
.join(" ")}
>
<HeroUICheckbox.Indicator>
{({ isSelected, isIndeterminate }) => {
if (isIndeterminate) {
return <FiMinus className="text-xs stroke-3" />;
}
if (isSelected) {
return <FiCheck className="text-xs stroke-3" />;
}
return null;
}}
</HeroUICheckbox.Indicator>
</HeroUICheckbox.Control>
{(label || description) && (
<div className="flex flex-col text-left">
{label && (
<span
className="
text-xs sm:text-sm font-medium
text-slate-800 dark:text-slate-200
group-hover:text-slate-950
dark:group-hover:text-white
transition-colors
"
>
{label}
</span>
)}
{description && (
<Description
className="
text-xs
text-slate-500 dark:text-slate-400
"
>
{description}
</Description>
)}
</div>
)}
</HeroUICheckbox.Content>
{errorMessage && (
<FieldError className="pl-6.5 text-xs">
{errorMessage}
</FieldError>
)}
</HeroUICheckbox>
);
};
Checkbox.displayName = "Checkbox";