import { HTMLAttributes, ReactNode } from "react"; import { ColorType, PrimaryColorType } from "../../types/colors"; import { Icon, IconType } from "../icon"; import Typography from "../typography/typography"; /** * @params EndIcon - The icon to be displayed at the end of the button * @params StartIcon - The icon to be displayed at the start of the button * @params children - The content of the button * @params className - Override or extend the styles applied to the component * @params color - Color of the button. It supports those theme colors that make sense for this component. * @params fullWidth - If true, the button will take up the full width of its container. * @params href - The URL to link to when the button is clicked. * @params shape - Shape of the button. It supports those theme shapes that make sense for this component. * @params size - Size of the button. It supports those theme sizes that make sense for this component. * @params variant - Variant of the button. It supports those theme variants that make sense for this component. */ export interface ButtonProps extends HTMLAttributes { endIcon?: IconType; icon?: IconType; label: string; className?: string; color?: Exclude; href?: string; shape?: "rounded" | "square"; size?: "sm" | "md" | "lg" | "xl" | "2xl"; variant?: "contained" | "outlined" | "light" | "text" | "link"; disabled?: boolean; online?: boolean; } const sizes = { sm: "px-[7px] py-1 gap-2", md: "px-2 py-[5px] gap-2", lg: "px-[9px] py-[5px] gap-2", xl: "px-2.5 py-1.5 gap-2", "2xl": "px-3.5 py-2 gap-3", }; const shapes = { rounded: "rounded-full", square: "rounded", }; /** * @param {ButtonProps} props * @returns Button component * @description This component is used to render a button * @example */ export function Button({ label, variant = "contained", color = "primary", size = "md", icon, endIcon, href, shape = "square", className = "", disabled = false, online = false, ...restProps }: ButtonProps) { const variants = { contained: { button: `bg-${color}-600 hover:bg-${color}-700 focus:ring-4 ring-${color}-100 disabled:bg-${color}-200`, typo: ``, icon: ``, }, outlined: { button: `bg-white border border-${color}-300 hover:bg-${color}-50 focus:ring-4 ring-${color}-100 disabled:border-${color}-200`, typo: ``, icon: ``, }, light: { button: `bg-${color}-50 hover:bg-${color}-100 focus:ring-4 ring-${color}-100 disabled:bg-${color}-25`, typo: ``, icon: ``, }, text: { button: `hover:bg-${color}-50`, typo: ``, icon: ``, }, link: { button: `cursor-pointer`, typo: ``, icon: ``, }, }; const classes = `group disabled:cursor-not-allowed ${variants[variant].button} ${shapes[shape]} ${className}`; const typoClassName = variant !== "contained" ? `group-hover:text-${color}-800 group-disabled:text-${color}-300` : ""; const iconClassName = variant !== "contained" ? `group-hover:stroke-${color}-800 group-disabled:stroke-${color}-300` : ""; const typoColor = variant === "contained" ? "white" : (`${color}-700` as ColorType); const typoSize = size === "2xl" ? "lg" : size === "xl" || size === "lg" ? "md" : "sm"; const iconSize = size === "2xl" ? 24 : 20; const statusDotColor = variant === "contained" ? "white" : disabled ? `${color}-300` : "success-500"; const children = (
{icon && ( )} {online && (
)} {label} {endIcon && ( )}
); return variant === "link" ? ( {children} ) : ( ); } export default Button;