ishaq101's picture
[KM-422] [EMA][FE] Interface prototype for External Demo
1ed65e9
"use client";
import { forwardRef } from "react";
import { cn } from "@/lib/utils";
interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
variant?: "primary" | "secondary" | "ghost" | "danger";
size?: "sm" | "md" | "lg";
loading?: boolean;
}
export const Button = forwardRef<HTMLButtonElement, ButtonProps>(
({ className, variant = "primary", size = "md", loading, children, disabled, ...props }, ref) => {
const base =
"inline-flex items-center justify-center gap-2 font-semibold rounded-xl transition-all duration-200 focus:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 disabled:opacity-50 disabled:cursor-not-allowed";
const variants = {
primary:
"bg-gradient-to-br from-brand-green-light to-brand-green text-white shadow-md shadow-brand-green/25 hover:shadow-lg hover:shadow-brand-green/30 hover:brightness-105 focus-visible:ring-brand-green",
secondary:
"bg-white border-1.5 border-neutral-200 text-neutral-700 hover:border-brand-green hover:text-brand-green hover:bg-brand-green-50 focus-visible:ring-brand-green",
ghost:
"bg-transparent text-neutral-600 hover:bg-neutral-100 hover:text-neutral-900 focus-visible:ring-neutral-400",
danger:
"bg-red-500 text-white hover:bg-red-600 shadow-sm focus-visible:ring-red-500",
};
const sizes = {
sm: "px-3 py-1.5 text-xs",
md: "px-5 py-2.5 text-sm",
lg: "px-7 py-3.5 text-base",
};
return (
<button
ref={ref}
disabled={disabled || loading}
className={cn(base, variants[variant], sizes[size], className)}
{...props}
>
{loading && (
<svg
className="animate-spin h-4 w-4"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
>
<circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4" />
<path
className="opacity-75"
fill="currentColor"
d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z"
/>
</svg>
)}
{children}
</button>
);
}
);
Button.displayName = "Button";