import * as React from 'react' import { Slot } from '@radix-ui/react-slot' import { cva, type VariantProps } from 'class-variance-authority' import { cn } from '@/lib/utils' /** * Button — shadcn-стиль, адаптирован под наш token palette. * * Variants per design handoff: * - primary — navy bg + on-accent text (deep coffee → cream). * - secondary — surface bg + ink text + line border (default outlined). * - ghost — transparent + hover:surface-2. * - danger — pink bg + on-accent text (destructive actions). * - link — accent text + underline-offset, no bg. * * Sizes: sm (28px), md (36px default), lg (40px), icon-sm (24px square), * icon (32px square). * * Use {@code asChild} (Radix Slot pattern) для рендера кастомного root * элемента — например {@code }. */ const buttonVariants = cva( [ 'inline-flex items-center justify-center gap-2 whitespace-nowrap', 'rounded-md text-body font-medium transition-colors', 'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-bg', 'disabled:pointer-events-none disabled:opacity-50', '[&_svg]:pointer-events-none [&_svg]:shrink-0', ].join(' '), { variants: { variant: { primary: 'bg-navy text-on-accent hover:opacity-90 active:opacity-95', secondary: 'border border-line bg-surface text-ink hover:bg-surface-2', ghost: 'text-ink hover:bg-surface-2', danger: 'bg-pink text-on-accent hover:opacity-90 active:opacity-95', link: 'text-accent underline-offset-4 hover:underline', }, size: { sm: 'h-7 px-2.5 text-cell', md: 'h-9 px-3.5', lg: 'h-10 px-4', 'icon-sm': 'h-6 w-6', icon: 'h-8 w-8', }, }, defaultVariants: { variant: 'primary', size: 'md', }, }, ) export type ButtonProps = React.ButtonHTMLAttributes & VariantProps & { asChild?: boolean leftIcon?: React.ReactNode rightIcon?: React.ReactNode /** Loading state — disables button + replaces leftIcon с inline spinner. */ loading?: boolean } export const Button = React.forwardRef( function Button( { className, variant, size, asChild, leftIcon, rightIcon, loading, disabled, children, ...props }, ref, ) { const Comp = asChild ? Slot : 'button' const renderedLeftIcon = loading ? ( ) : ( leftIcon ) return ( {renderedLeftIcon} {children} {rightIcon} ) }, ) export { buttonVariants }