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;