import * as React from "react" import { cva, type VariantProps } from "class-variance-authority" import { Slot } from "@radix-ui/react-slot" import { cn } from "@/lib/utils" /** * Premium luxury button system. * Gold primary (metallic gradient), sapphire secondary (navy gradient), shared hover/active. * Light reflection (::after) on primary and secondary. */ const buttonVariants = cva( [ "inline-flex items-center justify-center gap-2 whitespace-nowrap text-sm font-medium", "rounded-lg outline-none select-none", "transition-all duration-[280ms] ease-out", "hover:-translate-y-0.5 active:translate-y-0", "disabled:pointer-events-none disabled:opacity-50 disabled:translate-y-0 disabled:hover:translate-y-0 disabled:active:translate-y-0", "focus-visible:ring-[3px] focus-visible:ring-offset-2 focus-visible:ring-offset-background", "[&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0", "aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40", ].join(" "), { variants: { variant: { primary: [ "relative overflow-hidden", "bg-[linear-gradient(180deg,var(--btn-gold-from)_0%,var(--btn-gold-via)_50%,var(--btn-gold-to)_100%)]", "text-[var(--btn-gold-text)]", "shadow-[var(--btn-gold-shadow)]", "hover:shadow-[var(--btn-gold-shadow-hover)] hover:shadow-[var(--btn-gold-glow-hover)]", "active:shadow-[var(--btn-gold-shadow-active)]", "focus-visible:ring-primary/30", "after:content-[''] after:absolute after:inset-0 after:rounded-lg after:overflow-hidden after:pointer-events-none", "after:bg-[linear-gradient(105deg,transparent_0%,rgba(255,255,255,0.38)_50%,transparent_100%)]", "after:opacity-0 hover:after:opacity-100 hover:after:animate-[btn-shine_0.55s_ease-out]", ].join(" "), secondary: [ "relative overflow-hidden", "bg-[linear-gradient(180deg,var(--btn-sapphire-from)_0%,var(--btn-sapphire-to)_100%)]", "text-secondary-foreground", "shadow-[var(--btn-sapphire-shadow)]", "hover:shadow-[var(--btn-sapphire-shadow-hover)] hover:shadow-[var(--btn-sapphire-glow-hover)]", "active:shadow-[var(--btn-sapphire-shadow-active)]", "focus-visible:ring-secondary/30", "after:content-[''] after:absolute after:inset-0 after:rounded-lg after:overflow-hidden after:pointer-events-none", "after:bg-[linear-gradient(105deg,transparent_0%,rgba(255,255,255,0.25)_50%,transparent_100%)]", "after:opacity-0 hover:after:opacity-100 hover:after:animate-[btn-shine_0.55s_ease-out]", ].join(" "), outline: [ "border-2 border-secondary bg-transparent text-secondary", "shadow-sm", "hover:bg-secondary/10 hover:shadow-md hover:shadow-secondary/20", "active:bg-secondary/15 active:shadow-sm", "focus-visible:ring-secondary/30", ].join(" "), ghost: [ "bg-transparent", "hover:bg-accent hover:text-accent-foreground", "active:bg-accent/80", "focus-visible:ring-accent/30", ].join(" "), link: [ "text-primary underline-offset-4 shadow-none", "hover:underline hover:opacity-90 hover:-translate-y-0.5 active:translate-y-0", "focus-visible:ring-primary/20", ].join(" "), destructive: [ "bg-destructive text-destructive-foreground shadow-sm", "hover:bg-destructive/90 hover:shadow-md", "active:bg-destructive/95 active:shadow-sm active:translate-y-0", "focus-visible:ring-destructive/30", ].join(" "), default: [ "relative overflow-hidden", "bg-[linear-gradient(180deg,var(--btn-gold-from)_0%,var(--btn-gold-via)_50%,var(--btn-gold-to)_100%)]", "text-[var(--btn-gold-text)]", "shadow-[var(--btn-gold-shadow)]", "hover:shadow-[var(--btn-gold-shadow-hover)] hover:shadow-[var(--btn-gold-glow-hover)]", "active:shadow-[var(--btn-gold-shadow-active)]", "focus-visible:ring-primary/30", "after:content-[''] after:absolute after:inset-0 after:rounded-lg after:overflow-hidden after:pointer-events-none", "after:bg-[linear-gradient(105deg,transparent_0%,rgba(255,255,255,0.38)_50%,transparent_100%)]", "after:opacity-0 hover:after:opacity-100 hover:after:animate-[btn-shine_0.55s_ease-out]", ].join(" "), }, size: { default: "h-9 px-4 py-2 has-[>svg]:px-3", xs: "h-6 gap-1 rounded-md px-2 text-xs has-[>svg]:px-1.5 [&_svg:not([class*='size-'])]:size-3", sm: "h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5", lg: "h-10 rounded-lg px-6 has-[>svg]:px-4", icon: "size-9", "icon-xs": "size-6 rounded-md [&_svg:not([class*='size-'])]:size-3", "icon-sm": "size-8", "icon-lg": "size-10", }, }, defaultVariants: { variant: "default", size: "default", }, } ) function Button({ className, variant = "default", size = "default", asChild = false, ...props }: React.ComponentProps<"button"> & VariantProps & { asChild?: boolean }) { const Comp = asChild ? Slot : "button" return ( ) } export { Button, buttonVariants }