Files
core/src/shared/components/Button.js
T

86 lines
3.3 KiB
JavaScript

'use client';
import React from 'react';
const Button = ({
children,
onClick,
type = 'button',
variant = 'primary',
size = 'md',
disabled = false,
loading = false,
icon,
iconPosition = 'left',
className = '',
...props
}) => {
const baseClassName = 'cursor-pointer inline-flex items-center justify-center font-medium leading-none rounded-lg transition-all duration-[120ms] ease-out focus:outline-none focus:ring-1 disabled:opacity-50 disabled:cursor-not-allowed';
const variants = {
primary: 'bg-neutral-900 text-white hover:bg-neutral-800 focus:ring-neutral-900/20 dark:bg-white dark:text-black dark:hover:bg-neutral-100 dark:focus:ring-white/20',
secondary: 'bg-transparent border border-neutral-300 text-neutral-700 hover:bg-neutral-100 focus:ring-neutral-500/20 dark:bg-neutral-800/60 dark:border-neutral-700/50 dark:text-white dark:hover:bg-neutral-800/80 dark:focus:ring-neutral-600/20',
danger: 'bg-red-700/10 border border-red-800/30 text-red-700 hover:bg-red-700/15 focus:ring-red-700/20 dark:bg-red-600/10 dark:border-red-600/20 dark:text-red-600 dark:hover:bg-red-600/15 dark:focus:ring-red-600/20',
ghost: 'text-neutral-600 hover:text-neutral-900 hover:bg-neutral-100 focus:ring-neutral-500/20 dark:text-neutral-400 dark:hover:text-white dark:hover:bg-neutral-700/30 dark:focus:ring-neutral-600/20',
success: 'bg-green-700/10 border border-green-800/30 text-green-700 hover:bg-green-700/15 focus:ring-green-700/20 dark:bg-green-600/10 dark:border-green-600/20 dark:text-green-600 dark:hover:bg-green-600/15 dark:focus:ring-green-600/20',
warning: 'bg-yellow-700/10 border border-yellow-800/30 text-yellow-700 hover:bg-yellow-700/15 focus:ring-yellow-700/20 dark:bg-yellow-600/10 dark:border-yellow-600/20 dark:text-yellow-600 dark:hover:bg-yellow-600/15 dark:focus:ring-yellow-600/20'
};
const sizes = {
sm: '',
md: 'px-[12px] py-[7px] text-[12px] gap-1.5',
lg: ''
};
const iconOnlySizes = {
sm: '',
md: 'p-[7px] text-[12px]',
lg: ''
};
const isIconOnly = icon && !children;
const iconSizes = {
sm: '',
md: 'w-4 h-4',
lg: ''
};
const LoadingSpinner = () => (
<div className={`border-2 border-current border-t-transparent rounded-full animate-spin ${iconSizes[size]}`} />
);
const handleClick = (e) => {
if (!disabled && !loading && onClick) {
onClick(e);
}
};
const Icon = icon;
return (
<button
type={type}
onClick={handleClick}
disabled={disabled || loading}
className={`${baseClassName} ${variants[variant]} ${isIconOnly ? iconOnlySizes[size] : sizes[size]} ${className}`}
{...props}
>
{loading ? (
<LoadingSpinner />
) : (
<>
{Icon && iconPosition === 'left' && (
<Icon className={iconSizes[size]}/>
)}
{children}
{Icon && iconPosition === 'right' && (
<Icon className={iconSizes[size]}/>
)}
</>
)}
</button>
);
};
export default Button;