113 lines
2.8 KiB
TypeScript

import React from 'react';
interface ButtonProps {
children: React.ReactNode;
onClick?: () => void;
variant?: 'primary' | 'secondary' | 'danger';
size?: 'sm' | 'md' | 'lg';
loading?: boolean;
disabled?: boolean;
type?: 'button' | 'submit' | 'reset';
fullWidth?: boolean;
}
export function Button({
children,
onClick,
variant = 'primary',
size = 'md',
loading = false,
disabled = false,
type = 'button',
fullWidth = false,
}: ButtonProps) {
const variantStyles = {
primary: {
background: 'var(--color-accent-primary)',
color: 'white',
hover: 'var(--color-accent-hover)',
},
secondary: {
background: 'var(--color-background-tertiary)',
color: 'var(--color-text-primary)',
hover: 'var(--color-border-primary)',
},
danger: {
background: 'var(--color-error)',
color: 'white',
hover: '#dc2626',
},
};
const sizeStyles = {
sm: {
padding: 'var(--spacing-2) var(--spacing-3)',
fontSize: 'var(--font-size-sm)',
},
md: {
padding: 'var(--spacing-3) var(--spacing-5)',
fontSize: 'var(--font-size-base)',
},
lg: {
padding: 'var(--spacing-4) var(--spacing-6)',
fontSize: 'var(--font-size-lg)',
},
};
const style = variantStyles[variant];
const sizing = sizeStyles[size];
return (
<button
type={type}
onClick={onClick}
disabled={disabled || loading}
style={{
...sizing,
background: style.background,
color: style.color,
border: 'none',
borderRadius: 'var(--border-radius-md)',
fontWeight: 600,
cursor: disabled || loading ? 'not-allowed' : 'pointer',
display: 'inline-flex',
alignItems: 'center',
justifyContent: 'center',
gap: 'var(--spacing-2)',
transition: 'all 0.2s',
width: fullWidth ? '100%' : 'auto',
opacity: disabled || loading ? 0.6 : 1,
}}
onMouseEnter={(e) => {
if (!disabled && !loading) {
e.currentTarget.style.background = style.hover;
e.currentTarget.style.transform = 'translateY(-1px)';
e.currentTarget.style.boxShadow = 'var(--shadow-md)';
}
}}
onMouseLeave={(e) => {
if (!disabled && !loading) {
e.currentTarget.style.background = style.background;
e.currentTarget.style.transform = 'translateY(0)';
e.currentTarget.style.boxShadow = 'none';
}
}}
>
{loading && (
<span
className="animate-spin"
style={{
display: 'inline-block',
width: '1em',
height: '1em',
border: '2px solid currentColor',
borderTopColor: 'transparent',
borderRadius: '50%',
}}
/>
)}
{children}
</button>
);
}