import { forwardRef } from "react";
import type { ElementRef, ComponentProps } from "react";
import type { DataAttributeMap } from "./utils/buildDataAttributes";
import clsx from "clsx";
import buildDataAttributes from "./utils/buildDataAttributes";
type ButtonSizes = "small" | "standard";
type ButtonTones = "neutral" | "critical";
type ButtonVariants = "solid" | "ghost" | "soft" | "transparent";
type ButtonProps = {
variant?: ButtonVariants;
href?: string;
children: React.ReactNode;
onClick?:
| ComponentProps<"a">["onClick"]
| ComponentProps<"button">["onClick"];
disabled?: boolean;
size?: ButtonSizes;
tone?: ButtonTones;
isLoading?: boolean;
UNSAFE_className?: string;
data?: DataAttributeMap;
};
const variants = {
solid: "",
soft: "btn-ghost",
ghost: "btn-outline",
transparent: "btn-link",
};
const sizes = {
small: "btn-sm",
standard: "btn-md",
};
const tones: { [key in ButtonTones]: string } = {
neutral: "btn-primary",
critical: "btn-error",
};
// Full button coming: https://github.com/radix-ui/primitives/issues/892
export const Button = forwardRef<ElementRef<"a" | "button">, ButtonProps>(
(
{
tone = "neutral",
variant = "solid",
children,
onClick,
size = "standard",
disabled,
href,
isLoading,
UNSAFE_className,
data,
},
forwardedRef
) => {
const isLink = typeof href !== "undefined";
const Component = isLink ? "a" : "button";
return (
<Component
// @ts-ignore -- TODO fix
ref={forwardedRef}
className={clsx(
"btn",
variants[variant],
sizes[size],
tones[tone],
{ loading: isLoading },
UNSAFE_className
)}
href={href}
// @ts-ignore -- TODO fix
onClick={onClick}
{...(disabled ? { disabled: "disabled", tabIndex: "-1" } : {})}
{...(data ? buildDataAttributes(data) : undefined)}
>
{children}
</Component>
);
}
);
Button.displayName = "Button";
Lookup