79 lines
2.0 KiB
TypeScript
79 lines
2.0 KiB
TypeScript
import {
|
|
type ComponentPropsWithoutRef,
|
|
forwardRef,
|
|
type ReactNode,
|
|
} from "react";
|
|
|
|
import { Icon } from "../Icon/Icon";
|
|
import { SpinnerSvg } from "../../assets/svg/SpinnerSvg";
|
|
|
|
export type ButtonSize = "xs" | "sm" | "md" | "lg";
|
|
|
|
export type ButtonProps = ComponentPropsWithoutRef<"button"> & {
|
|
size?: ButtonSize;
|
|
variant?: "filled" | "outline" | "subtle" | "ghost";
|
|
shape?: "rounded" | "square" | "circle";
|
|
brand?: "success" | "danger" | "info" | "warning" | "emphasize";
|
|
} & {
|
|
iconOnly?: boolean;
|
|
hideIcon?: boolean;
|
|
loading?: boolean;
|
|
} & {
|
|
iconSvg?: ReactNode;
|
|
loadingIconSvg?: ReactNode;
|
|
};
|
|
|
|
export const Button = forwardRef<HTMLButtonElement, ButtonProps>(
|
|
(props, ref) => {
|
|
const {
|
|
size = "md",
|
|
variant = "filled",
|
|
shape = "rounded",
|
|
brand = "info",
|
|
// ===========================
|
|
iconOnly = false,
|
|
hideIcon = false,
|
|
loading,
|
|
disabled = false,
|
|
// =========================
|
|
className = "",
|
|
children,
|
|
// ==========================
|
|
iconSvg,
|
|
loadingIconSvg = <SpinnerSvg />,
|
|
...rest
|
|
} = props;
|
|
|
|
const mergedClass = cpm(
|
|
itemSizeRecipe({ size, shape, iconOnly, longPadding: false }),
|
|
variantRecipe({ variant, disabled }),
|
|
brandRecipe({ brand }),
|
|
className,
|
|
);
|
|
|
|
const contentClass = loading
|
|
? cpm("visible--hidden", inlineSizeRecipe({ size }))
|
|
: inlineSizeRecipe({ size });
|
|
|
|
const loadingIconClass = loading ? "position--absolute" : "";
|
|
|
|
const icon = <Icon size={size}>{iconSvg}</Icon>;
|
|
const loadingIcon = (
|
|
<Icon className={loadingIconClass} size={size}>
|
|
{loadingIconSvg}
|
|
</Icon>
|
|
);
|
|
|
|
return (
|
|
<button ref={ref} className={mergedClass} disabled={disabled} {...rest}>
|
|
<span className={contentClass}>
|
|
{!hideIcon && iconSvg && icon}
|
|
{!iconOnly && children}
|
|
</span>
|
|
{loading && loadingIcon}
|
|
</button>
|
|
);
|
|
},
|
|
);
|
|
Button.displayName = "Button";
|