148 lines
3.7 KiB
TypeScript
148 lines
3.7 KiB
TypeScript
import { Button as ShadcnButton, ButtonProps } from "@/components/ui/button";
|
|
import {
|
|
FontName,
|
|
fonts,
|
|
iconMap,
|
|
sidePlacements,
|
|
} from "@/front/lib/constants";
|
|
import { cn } from "@/lib/utils";
|
|
import { CustomButtonVariant, IconConfig } from "@/types/front";
|
|
import { Link } from "@inertiajs/react";
|
|
|
|
type CustomSize = "xs" | "md";
|
|
|
|
type ThemeButtonProps = Omit<ButtonProps, "variant" | "size"> & {
|
|
variant?: ButtonProps["variant"] | CustomButtonVariant;
|
|
size?: ButtonProps["size"] | CustomSize;
|
|
icon?: IconConfig;
|
|
isBold?: boolean;
|
|
font?: FontName;
|
|
link?: {
|
|
href: string;
|
|
label: string;
|
|
};
|
|
};
|
|
|
|
const customVariantSizes: Record<CustomSize, string> = {
|
|
xs: "h-7 px-3 text-sm",
|
|
md: "h-10 px-6 py-2 text-md",
|
|
};
|
|
|
|
const customVariantStyles: Record<CustomButtonVariant, string> = {
|
|
tertiary:
|
|
"bg-primary-foreground text-background hover:bg-primary-foreground/90",
|
|
inverted: "bg-background hover:bg-secondary/90",
|
|
};
|
|
|
|
export default function Button({
|
|
icon,
|
|
isBold = true,
|
|
font = fonts.GOTHAM,
|
|
size,
|
|
variant,
|
|
children,
|
|
className,
|
|
asChild,
|
|
link,
|
|
...props
|
|
}: ThemeButtonProps) {
|
|
const Icon = icon ? iconMap[icon.icon] : undefined;
|
|
|
|
const customVariant =
|
|
variant && variant in customVariantStyles
|
|
? customVariantStyles[variant as CustomButtonVariant]
|
|
: "";
|
|
|
|
const getSizeClasses = () => {
|
|
if (size && size in customVariantSizes) {
|
|
return customVariantSizes[size as CustomSize];
|
|
}
|
|
return "h-9 px-5 text-md";
|
|
};
|
|
|
|
const iconClassName = icon?.className ?? "";
|
|
if (link && link.href && link.label) {
|
|
return (
|
|
<ShadcnButton
|
|
variant={variant as ButtonProps["variant"]}
|
|
className={cn(
|
|
"rounded-full w-fit",
|
|
isBold ? "font-bold" : "font-normal",
|
|
font,
|
|
className,
|
|
getSizeClasses(),
|
|
customVariant,
|
|
)}
|
|
asChild
|
|
/* eslint-disable react/jsx-props-no-spreading */
|
|
{...props}
|
|
>
|
|
<Link
|
|
href={link.href}
|
|
className="flex items-center justify-center gap-2"
|
|
>
|
|
{icon?.placement !== sidePlacements.RIGHT && Icon && (
|
|
<Icon className={cn(iconClassName)} />
|
|
)}
|
|
{link.label}
|
|
{icon?.placement === sidePlacements.RIGHT && Icon && (
|
|
<Icon className={cn(iconClassName)} />
|
|
)}
|
|
</Link>
|
|
</ShadcnButton>
|
|
);
|
|
}
|
|
|
|
if (asChild) {
|
|
return (
|
|
<ShadcnButton
|
|
variant={variant as ButtonProps["variant"]}
|
|
className={cn(
|
|
"rounded-full w-fit",
|
|
isBold ? "font-bold" : "font-normal",
|
|
font,
|
|
className,
|
|
getSizeClasses(),
|
|
customVariant,
|
|
)}
|
|
asChild
|
|
/* eslint-disable react/jsx-props-no-spreading */
|
|
{...props}
|
|
>
|
|
<div>
|
|
{icon?.placement !== sidePlacements.RIGHT && Icon && (
|
|
<Icon className={cn(iconClassName)} />
|
|
)}
|
|
{children}
|
|
{icon?.placement === sidePlacements.RIGHT && Icon && (
|
|
<Icon className={cn(iconClassName)} />
|
|
)}
|
|
</div>
|
|
</ShadcnButton>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<ShadcnButton
|
|
variant={variant as ButtonProps["variant"]}
|
|
className={cn(
|
|
"rounded-full w-fit",
|
|
isBold ? "font-bold" : "font-normal",
|
|
font,
|
|
className,
|
|
getSizeClasses(),
|
|
customVariant,
|
|
)}
|
|
/* eslint-disable react/jsx-props-no-spreading */
|
|
{...props}
|
|
>
|
|
{icon?.placement !== sidePlacements.RIGHT && Icon && (
|
|
<Icon className={cn(iconClassName)} />
|
|
)}
|
|
{children}
|
|
{icon?.placement === sidePlacements.RIGHT && Icon && (
|
|
<Icon className={cn(iconClassName)} />
|
|
)}
|
|
</ShadcnButton>
|
|
);
|
|
}
|