58 lines
1.9 KiB
TypeScript
58 lines
1.9 KiB
TypeScript
import type { ButtonHTMLAttributes } from "react";
|
|
|
|
export type ButtonVariant = "primary" | "secondary" | "ghost" | "success" | "danger";
|
|
export type ButtonSize = "sm" | "md" | "lg";
|
|
|
|
const VARIANTS: Record<ButtonVariant, string> = {
|
|
primary:
|
|
"bg-linear-to-b from-amber-300 to-amber-500 text-space-950 shadow-glow-amber hover:from-amber-200 hover:to-amber-400",
|
|
secondary:
|
|
"border border-space-500 bg-space-800/80 text-ink-50 hover:border-amber-400/60 hover:bg-space-700",
|
|
ghost: "text-ink-300 hover:bg-white/5 hover:text-ink-50",
|
|
success:
|
|
"bg-linear-to-b from-emerald-300 to-emerald-500 text-space-950 shadow-glow-emerald hover:from-emerald-200 hover:to-emerald-400",
|
|
danger: "border border-rose-500/60 bg-rose-500/15 text-rose-200 hover:bg-rose-500/25",
|
|
};
|
|
|
|
const SIZES: Record<ButtonSize, string> = {
|
|
sm: "min-h-9 px-3 text-xs",
|
|
md: "min-h-11 px-4 text-sm",
|
|
lg: "min-h-13 px-6 text-base",
|
|
};
|
|
|
|
/** Classes for anything that should look like a button, e.g. a router `Link`. */
|
|
export function buttonClass(
|
|
variant: ButtonVariant = "primary",
|
|
size: ButtonSize = "md",
|
|
block = false,
|
|
): string {
|
|
return [
|
|
"inline-flex items-center justify-center gap-2 rounded-lg font-display font-semibold uppercase tracking-wider",
|
|
"transition duration-150 select-none active:translate-y-px active:scale-[0.98]",
|
|
"disabled:pointer-events-none disabled:opacity-40 disabled:shadow-none disabled:saturate-50",
|
|
VARIANTS[variant],
|
|
SIZES[size],
|
|
block ? "w-full" : "",
|
|
].join(" ");
|
|
}
|
|
|
|
export interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {
|
|
variant?: ButtonVariant;
|
|
size?: ButtonSize;
|
|
/** Full width. */
|
|
block?: boolean;
|
|
}
|
|
|
|
export function Button({
|
|
variant,
|
|
size,
|
|
block,
|
|
className = "",
|
|
type = "button",
|
|
...rest
|
|
}: ButtonProps) {
|
|
return (
|
|
<button type={type} className={`${buttonClass(variant, size, block)} ${className}`} {...rest} />
|
|
);
|
|
}
|