Files
igny8/frontend/src/components/ui/button/Button.tsx
2025-11-09 10:27:02 +00:00

72 lines
2.2 KiB
TypeScript

/**
* Button Component
*
* 🔒 STYLE LOCKED - See DESIGN_SYSTEM.md for available variants and sizes.
* Do not modify variants or add new ones without updating DESIGN_SYSTEM.md first.
*/
import { ReactNode, forwardRef } from "react";
interface ButtonProps {
children: ReactNode; // Button text or content
size?: "sm" | "md"; // Button size
variant?: "primary" | "outline" | "secondary" | "success"; // Button variant
startIcon?: ReactNode; // Icon before the text
endIcon?: ReactNode; // Icon after the text
onClick?: () => void; // Click handler
disabled?: boolean; // Disabled state
className?: string; // Additional classes
type?: "button" | "submit" | "reset"; // Button type
}
const Button = forwardRef<HTMLButtonElement, ButtonProps>(({
children,
size = "md",
variant = "primary",
startIcon,
endIcon,
onClick,
className = "",
disabled = false,
type = "button",
}, ref) => {
// Size Classes
const sizeClasses = {
sm: "px-3 py-1.5 text-xs h-8",
md: "px-3 py-2 text-sm h-9",
};
// Variant Classes
const variantClasses = {
primary:
"bg-brand-500 text-white shadow-theme-xs hover:bg-brand-600 disabled:bg-brand-300",
outline:
"bg-white text-gray-700 ring-1 ring-inset ring-gray-300 hover:bg-gray-50 dark:bg-gray-800 dark:text-gray-400 dark:ring-gray-700 dark:hover:bg-white/[0.03] dark:hover:text-gray-300",
secondary:
"bg-gray-500 text-white border border-gray-500 hover:bg-gray-600 hover:border-gray-600 dark:bg-gray-500 dark:border-gray-500 dark:hover:bg-gray-600 dark:hover:border-gray-600",
success:
"bg-success-500 text-white shadow-theme-xs hover:bg-success-600 disabled:bg-success-300",
};
return (
<button
ref={ref}
type={type}
className={`inline-flex items-center justify-center gap-2 rounded-lg transition ${className} ${
sizeClasses[size]
} ${variantClasses[variant]} ${
disabled ? "cursor-not-allowed opacity-50" : ""
}`}
onClick={onClick}
disabled={disabled}
>
{startIcon && <span className="flex items-center">{startIcon}</span>}
{children}
{endIcon && <span className="flex items-center">{endIcon}</span>}
</button>
);
});
Button.displayName = "Button";
export default Button;