'use client'; import React from 'react'; import { Button as AntButton, ButtonProps as AntButtonProps } from 'antd'; import { motion, MotionProps } from 'framer-motion'; import { cn } from '@/utils/cn'; import { Typography } from './Typography'; // Extend Ant Design ButtonProps with custom variants aligned to brand system interface CustomButtonProps { variant?: 'primary' | 'secondary' | 'tertiary' | 'ghost' | 'gradient' | 'walnut'; size?: 'small' | 'regular' | 'large'; fullWidth?: boolean; animated?: boolean; icon?: React.ReactNode; iconPosition?: 'left' | 'right'; } type ButtonProps = Omit & CustomButtonProps & Partial; const MotionButton = motion(AntButton); export const Button: React.FC = ({ variant = 'primary', size = 'regular', fullWidth = false, animated = true, icon, iconPosition = 'left', className, children, ...antProps }) => { const getVariantStyles = () => { const baseStyles = { fontFamily: 'var(--font-body)', fontWeight: 600, lineHeight: 'var(--leading-tight)', letterSpacing: 'var(--tracking-wider)', borderRadius: 'var(--radius-button)', transition: 'all var(--duration-normal) var(--easing-ease-out)', cursor: 'pointer', border: 'none', display: 'flex', alignItems: 'center', justifyContent: 'center', gap: icon ? 'var(--space-sm)' : '0', }; switch (variant) { case 'primary': return { ...baseStyles, backgroundColor: 'var(--interactive-primary)', color: '#ffffff', boxShadow: 'var(--shadow-button)', }; case 'secondary': return { ...baseStyles, backgroundColor: 'transparent', color: 'var(--interactive-primary)', border: '2px solid var(--interactive-primary)', }; case 'tertiary': return { ...baseStyles, backgroundColor: 'var(--interactive-secondary)', color: 'var(--text-inverse)', }; case 'ghost': return { ...baseStyles, backgroundColor: 'transparent', color: 'var(--text-secondary)', border: '1px solid var(--border-secondary)', }; case 'gradient': return { ...baseStyles, background: 'linear-gradient(135deg, var(--color-primary) 0%, var(--color-success) 100%)', color: '#ffffff', boxShadow: 'var(--shadow-button)', }; case 'walnut': return { ...baseStyles, backgroundColor: 'var(--chorus-walnut-deep)', color: '#ffffff', boxShadow: 'var(--shadow-button)', }; default: return baseStyles; } }; const getSizeStyles = () => { switch (size) { case 'small': return { fontSize: 'var(--text-interface-small)', padding: 'var(--space-sm) var(--space-md)', minHeight: '36px', }; case 'large': return { fontSize: 'var(--text-interface)', padding: 'var(--space-lg) var(--space-2xl)', minHeight: '52px', }; default: // regular return { fontSize: 'var(--text-interface)', padding: 'var(--space-md) var(--space-xl)', minHeight: '44px', }; } }; const getHoverStyles = () => { switch (variant) { case 'primary': return { backgroundColor: 'var(--interactive-primary-hover)', boxShadow: 'var(--shadow-button-hover)', transform: 'translateY(-2px)', }; case 'secondary': return { backgroundColor: 'var(--interactive-primary)', color: '#ffffff', transform: 'translateY(-2px)', boxShadow: 'var(--shadow-button)', }; case 'tertiary': return { backgroundColor: 'var(--interactive-secondary-hover)', transform: 'translateY(-2px)', boxShadow: 'var(--shadow-md)', }; case 'ghost': return { color: 'var(--text-primary)', borderColor: 'var(--border-primary)', backgroundColor: 'var(--bg-tertiary)', }; case 'gradient': return { boxShadow: 'var(--shadow-button-hover)', transform: 'translateY(-2px)', }; case 'walnut': return { backgroundColor: 'var(--chorus-walnut-medium)', boxShadow: 'var(--shadow-button-hover)', transform: 'translateY(-2px)', }; default: return {}; } }; const buttonStyles = { ...getVariantStyles(), ...getSizeStyles(), width: fullWidth ? '100%' : 'auto', }; const animationProps = animated ? { whileHover: getHoverStyles(), whileTap: { transform: 'translateY(0)', boxShadow: variant === 'primary' || variant === 'gradient' || variant === 'walnut' ? 'var(--shadow-button)' : undefined }, transition: { duration: 0.2, ease: [0, 0, 0.2, 1] }, } : {}; const renderContent = () => { if (!icon) { return {children}; } return ( <> {iconPosition === 'left' && icon} {children} {iconPosition === 'right' && icon} ); }; if (animated) { return ( {renderContent()} ); } return ( {renderContent()} ); }; // Specific button variants for common use cases aligned to brand system export const PrimaryButton: React.FC> = (props) => (