Sacha VAUDEY 57f5807876
Some checks failed
Build and Test / Classic Build (pull_request) Failing after 2m19s
Build and Test / Docker Build (pull_request) Has been skipped
optimize archi
2025-09-14 12:54:18 +02:00

75 lines
2.7 KiB
TypeScript

import React from 'react';
import { cn, commonClasses } from '@/lib/utils';
interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
variant?: 'primary' | 'discord' | 'auth' | 'secondary' | 'ghost' | 'outline';
size?: 'sm' | 'md' | 'lg';
fullWidth?: boolean;
leftIcon?: React.ReactNode;
rightIcon?: React.ReactNode;
loading?: boolean;
children: React.ReactNode;
}
// Factorisation des classes de taille et de variante
const sizeClasses = {
sm: 'px-4 py-2 text-sm',
md: 'px-6 py-3 text-base',
lg: 'px-8 py-4 text-lg',
} as const;
const variantClasses = {
primary: 'bg-gradient-to-r from-blue-600 to-blue-500 text-white shadow-lg hover:shadow-xl hover:from-blue-700 hover:to-blue-600 border-2 border-blue-600/20',
discord: 'bg-gradient-to-r from-indigo-600 to-purple-600 text-white shadow-lg hover:shadow-xl hover:from-indigo-700 hover:to-purple-700 border-2 border-indigo-600/20',
auth: 'bg-gradient-to-r from-blue-500 to-blue-400 text-white shadow-lg hover:shadow-xl hover:from-blue-600 hover:to-blue-500 border-2 border-blue-500/20',
secondary: 'bg-white text-blue-700 border-2 border-blue-600 shadow-md hover:shadow-lg hover:bg-blue-50',
outline: 'bg-transparent text-gray-700 border-2 border-gray-300 hover:bg-gray-50 hover:border-gray-400',
ghost: 'bg-transparent text-gray-700 hover:bg-gray-100',
} as const;
// Composant loading spinner réutilisable
const LoadingSpinner = () => (
<svg className="animate-spin -ml-1 mr-3 h-5 w-5" 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"></circle>
<path className="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
</svg>
);
export const Button: React.FC<ButtonProps> = ({
variant = 'primary',
size = 'md',
fullWidth = false,
leftIcon,
rightIcon,
loading = false,
children,
className = '',
disabled,
...props
}) => {
const isDisabled = disabled || loading;
return (
<button
className={cn(
commonClasses.buttonBase,
commonClasses.transition,
commonClasses.hoverScale,
'focus:ring-4 focus:ring-blue-300',
sizeClasses[size],
variantClasses[variant],
fullWidth && 'w-full',
isDisabled && 'opacity-50 cursor-not-allowed transform-none',
className
)}
disabled={isDisabled}
{...props}
>
{loading && <LoadingSpinner />}
{leftIcon && !loading && <span className="mr-2">{leftIcon}</span>}
{children}
{rightIcon && !loading && <span className="ml-2">{rightIcon}</span>}
</button>
);
};