import { Loader2 } from 'lucide-react'; import React, { MouseEventHandler, ReactNode, forwardRef } from 'react'; import { Box } from './Box'; import { Icon } from './Icon'; export interface ButtonProps { children: ReactNode; onClick?: MouseEventHandler; variant?: 'primary' | 'secondary' | 'danger' | 'ghost' | 'success' | 'discord' | 'race-final' | any; size?: 'sm' | 'md' | 'lg' | any; disabled?: boolean; isLoading?: boolean; type?: 'button' | 'submit' | 'reset'; icon?: ReactNode; fullWidth?: boolean; as?: 'button' | 'a' | any; href?: string; target?: string; rel?: string; title?: string; className?: string; style?: React.CSSProperties; rounded?: boolean | string | any; mt?: number | any; p?: number | any; px?: number | any; py?: number | any; w?: string | number | any; h?: string | number | any; bg?: string | any; color?: string | any; borderColor?: string | any; hoverBorderColor?: string | any; letterSpacing?: string | any; fontSize?: string | any; transition?: boolean | any; center?: boolean | any; justifyContent?: string | any; shadow?: string | any; position?: string | any; borderWidth?: string | any; aspectRatio?: string | any; border?: boolean | any; } /** * Button - Redesigned for "Modern Precision" theme. * Includes extensive compatibility props to prevent app-wide breakage. */ export const Button = forwardRef(({ children, onClick, variant = 'primary', size = 'md', disabled = false, isLoading = false, type = 'button', icon, fullWidth = false, as = 'button', href, target, rel, title, className, style, rounded, mt, p, px, py, w, h, bg, color, borderColor, hoverBorderColor, letterSpacing, fontSize, transition, center, justifyContent, shadow, position, borderWidth, aspectRatio, border, }, ref) => { const baseClasses = 'inline-flex items-center justify-center focus-visible:outline focus-visible:outline-1 focus-visible:outline-offset-2 active:opacity-80 uppercase tracking-widest font-bold transition-all duration-150 ease-in-out'; const variantClasses = { primary: 'bg-[var(--ui-color-intent-primary)] text-white hover:opacity-90 focus-visible:outline-[var(--ui-color-intent-primary)] shadow-[0_0_15px_rgba(25,140,255,0.2)]', secondary: 'bg-[var(--ui-color-bg-surface)] text-white border border-[var(--ui-color-border-default)] hover:bg-[var(--ui-color-border-default)] focus-visible:outline-[var(--ui-color-intent-primary)]', danger: 'bg-[var(--ui-color-intent-critical)] text-white hover:opacity-90 focus-visible:outline-[var(--ui-color-intent-critical)]', ghost: 'bg-transparent text-[var(--ui-color-text-low)] hover:text-[var(--ui-color-text-high)] hover:bg-white/5 focus-visible:outline-[var(--ui-color-text-low)]', success: 'bg-[var(--ui-color-intent-success)] text-[var(--ui-color-bg-base)] hover:opacity-90 focus-visible:outline-[var(--ui-color-intent-success)]', discord: 'bg-[#5865F2] text-white hover:bg-[#4752C4] focus-visible:outline-[#5865F2]', 'race-final': 'bg-[var(--ui-color-intent-success)] text-[var(--ui-color-bg-base)] hover:opacity-90 focus-visible:outline-[var(--ui-color-intent-success)]', }; const sizeClasses = { sm: 'min-h-[32px] px-3 py-1 text-[10px]', md: 'min-h-[40px] px-4 py-2 text-xs', lg: 'min-h-[48px] px-6 py-3 text-sm' }; const disabledClasses = (disabled || isLoading) ? 'opacity-40 cursor-not-allowed' : 'cursor-pointer'; const widthClasses = fullWidth ? 'w-full' : ''; const classes = [ baseClasses, variantClasses[variant as keyof typeof variantClasses] || variantClasses.primary, sizeClasses[size as keyof typeof sizeClasses] || sizeClasses.md, disabledClasses, widthClasses, rounded === true ? 'rounded-full' : (typeof rounded === 'string' ? `rounded-${rounded}` : 'rounded-none'), center ? 'items-center justify-center' : '', className, ].filter(Boolean).join(' '); const combinedStyle: React.CSSProperties = { ...style, ...(mt !== undefined ? { marginTop: typeof mt === 'number' ? `${mt * 0.25}rem` : mt } : {}), ...(p !== undefined ? { padding: typeof p === 'number' ? `${p * 0.25}rem` : p } : {}), ...(px !== undefined ? { paddingLeft: typeof px === 'number' ? `${px * 0.25}rem` : px, paddingRight: typeof px === 'number' ? `${px * 0.25}rem` : px } : {}), ...(py !== undefined ? { paddingTop: typeof py === 'number' ? `${py * 0.25}rem` : py, paddingBottom: typeof py === 'number' ? `${py * 0.25}rem` : py } : {}), ...(w !== undefined ? { width: w } : {}), ...(h !== undefined ? { height: h } : {}), ...(bg ? { backgroundColor: bg.startsWith('bg-') ? undefined : bg } : {}), ...(color ? { color: color.startsWith('text-') ? undefined : color } : {}), ...(borderColor ? { borderColor: borderColor.startsWith('border-') ? undefined : borderColor, borderStyle: 'solid', borderWidth: '1px' } : {}), ...(letterSpacing ? { letterSpacing } : {}), ...(fontSize ? { fontSize } : {}), ...(justifyContent ? { justifyContent } : {}), ...(shadow ? { boxShadow: shadow } : {}), ...(position ? { position } : {}), ...(borderWidth ? { borderWidth } : {}), ...(aspectRatio ? { aspectRatio } : {}), }; const content = ( {isLoading && } {!isLoading && icon} {children} ); const Tag = as === 'a' ? 'a' : 'button'; return ( {content} ); }); Button.displayName = 'Button';