Some checks failed
Deploy to Test Environment / deploy-to-test (push) Failing after 12s
82 lines
2.6 KiB
TypeScript
82 lines
2.6 KiB
TypeScript
import React from 'react';
|
|
import { LoadingSpinner } from './LoadingSpinner';
|
|
|
|
export interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
|
|
variant?: 'primary' | 'secondary' | 'danger' | 'ghost';
|
|
size?: 'sm' | 'md' | 'lg';
|
|
isLoading?: boolean;
|
|
leftIcon?: React.ReactNode;
|
|
rightIcon?: React.ReactNode;
|
|
fullWidth?: boolean;
|
|
}
|
|
|
|
export const Button: React.FC<ButtonProps> = ({
|
|
variant = 'primary',
|
|
size = 'md',
|
|
isLoading = false,
|
|
leftIcon,
|
|
rightIcon,
|
|
fullWidth = false,
|
|
className = '',
|
|
children,
|
|
disabled,
|
|
...props
|
|
}) => {
|
|
const baseClasses =
|
|
'inline-flex items-center justify-center font-bold rounded-lg transition-colors duration-300 focus:outline-none focus:ring-2 focus:ring-offset-2 disabled:cursor-not-allowed';
|
|
|
|
const variantClasses = {
|
|
primary:
|
|
'bg-brand-secondary hover:bg-brand-dark text-white focus:ring-brand-primary disabled:bg-gray-400 disabled:hover:bg-gray-400',
|
|
secondary:
|
|
'bg-gray-200 hover:bg-gray-300 dark:bg-gray-700 dark:hover:bg-gray-600 text-gray-700 dark:text-gray-200 focus:ring-gray-400 disabled:bg-gray-100 disabled:hover:bg-gray-100 dark:disabled:bg-gray-800 dark:disabled:hover:bg-gray-800 disabled:text-gray-400',
|
|
danger:
|
|
'bg-red-100 hover:bg-red-200 dark:bg-red-900/50 dark:hover:bg-red-900/70 text-red-700 dark:text-red-300 focus:ring-red-500 disabled:bg-red-50 disabled:hover:bg-red-50 dark:disabled:bg-red-900/20 dark:disabled:hover:bg-red-900/20 disabled:text-red-300',
|
|
ghost:
|
|
'bg-transparent hover:bg-gray-100 dark:hover:bg-gray-800 text-gray-700 dark:text-gray-200 focus:ring-gray-400 disabled:text-gray-400 disabled:hover:bg-transparent',
|
|
};
|
|
|
|
const sizeClasses = {
|
|
sm: 'px-3 py-1.5 text-sm',
|
|
md: 'px-4 py-2 text-base',
|
|
lg: 'px-6 py-3 text-lg',
|
|
};
|
|
|
|
const widthClass = fullWidth ? 'w-full' : '';
|
|
|
|
const iconSizeClasses = {
|
|
sm: 'w-4 h-4',
|
|
md: 'w-5 h-5',
|
|
lg: 'w-6 h-6',
|
|
};
|
|
|
|
const isDisabled = disabled || isLoading;
|
|
|
|
return (
|
|
<button
|
|
className={`${baseClasses} ${variantClasses[variant]} ${sizeClasses[size]} ${widthClass} ${className}`}
|
|
disabled={isDisabled}
|
|
{...props}
|
|
>
|
|
{isLoading ? (
|
|
<>
|
|
<span className={`${iconSizeClasses[size]} mr-2`}>
|
|
<LoadingSpinner />
|
|
</span>
|
|
{children}
|
|
</>
|
|
) : (
|
|
<>
|
|
{leftIcon && (
|
|
<span className={`${iconSizeClasses[size]} mr-2 flex-shrink-0`}>{leftIcon}</span>
|
|
)}
|
|
{children}
|
|
{rightIcon && (
|
|
<span className={`${iconSizeClasses[size]} ml-2 flex-shrink-0`}>{rightIcon}</span>
|
|
)}
|
|
</>
|
|
)}
|
|
</button>
|
|
);
|
|
};
|