erp-core-frontend-v2/src/shared/components/atoms/Button/Button.tsx
rckrdmrd b30f3339bd Migración desde erp-core/frontend - Estándar multi-repo v2
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-16 08:10:41 -06:00

80 lines
2.3 KiB
TypeScript

import { forwardRef, type ButtonHTMLAttributes, type ReactNode } from 'react';
import { cva, type VariantProps } from 'class-variance-authority';
import { cn } from '@utils/cn';
import { Loader2 } from 'lucide-react';
const buttonVariants = cva(
'inline-flex items-center justify-center rounded-md font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50',
{
variants: {
variant: {
primary: 'bg-primary-600 text-white hover:bg-primary-700 focus-visible:ring-primary-500',
secondary: 'bg-secondary-100 text-secondary-900 hover:bg-secondary-200 focus-visible:ring-secondary-500',
outline: 'border border-gray-300 bg-white hover:bg-gray-50 focus-visible:ring-gray-500',
ghost: 'hover:bg-gray-100 focus-visible:ring-gray-500',
danger: 'bg-danger-600 text-white hover:bg-danger-700 focus-visible:ring-danger-500',
link: 'text-primary-600 underline-offset-4 hover:underline focus-visible:ring-primary-500',
},
size: {
sm: 'h-8 px-3 text-sm',
md: 'h-10 px-4',
lg: 'h-12 px-6 text-lg',
icon: 'h-10 w-10',
},
fullWidth: {
true: 'w-full',
},
},
defaultVariants: {
variant: 'primary',
size: 'md',
},
}
);
export interface ButtonProps
extends ButtonHTMLAttributes<HTMLButtonElement>,
VariantProps<typeof buttonVariants> {
children: ReactNode;
isLoading?: boolean;
leftIcon?: ReactNode;
rightIcon?: ReactNode;
}
export const Button = forwardRef<HTMLButtonElement, ButtonProps>(
(
{
children,
variant,
size,
fullWidth,
isLoading,
leftIcon,
rightIcon,
disabled,
className,
...props
},
ref
) => {
return (
<button
ref={ref}
className={cn(buttonVariants({ variant, size, fullWidth }), className)}
disabled={disabled || isLoading}
{...props}
>
{isLoading ? (
<Loader2 className="mr-2 h-4 w-4 animate-spin" />
) : leftIcon ? (
<span className="mr-2">{leftIcon}</span>
) : null}
{children}
{rightIcon && !isLoading && <span className="ml-2">{rightIcon}</span>}
</button>
);
}
);
Button.displayName = 'Button';