"use client"; import React from "react"; import { cn } from "@/lib/utils"; export type CandyButtonVariant = | "emerald" | "ruby" | "amber" | "violet" | "azure" | "obsidian" | "pearl"; export type CandyButtonSize = "sm" | "default" | "lg" | "icon"; export interface CandyButtonProps extends React.ButtonHTMLAttributes { as?: React.ElementType; href?: string; target?: string; rel?: string; variant?: CandyButtonVariant; size?: CandyButtonSize; color?: string; glow?: boolean; glassSheen?: boolean; leftIcon?: React.ReactNode; rightIcon?: React.ReactNode; } const variantStyles: Record = { emerald: "bg-[radial-gradient(120%_80%_at_50%_70%,#006a66_0%,#003835_100%)] text-white shadow-[0px_4px_24px_-6px_rgba(0,106,102,0.5),inset_0px_1px_4px_0px_rgba(255,255,255,0.4),inset_0px_-2px_4px_0px_rgba(0,0,0,0.15)] hover:shadow-[0px_6px_28px_-4px_rgba(0,106,102,0.65),inset_0px_1px_4px_0px_rgba(255,255,255,0.5),inset_0px_-2px_4px_0px_rgba(0,0,0,0.15)]", ruby: "bg-[radial-gradient(120%_80%_at_50%_70%,#e11d48_0%,#9f1239_100%)] text-white shadow-[0px_4px_24px_-6px_rgba(225,29,72,0.5),inset_0px_1px_4px_0px_rgba(255,255,255,0.4),inset_0px_-2px_4px_0px_rgba(0,0,0,0.15)] hover:shadow-[0px_6px_28px_-4px_rgba(225,29,72,0.65),inset_0px_1px_4px_0px_rgba(255,255,255,0.5),inset_0px_-2px_4px_0px_rgba(0,0,0,0.15)]", amber: "bg-[radial-gradient(120%_80%_at_50%_70%,#f59e0b_0%,#b45309_100%)] text-white shadow-[0px_4px_24px_-6px_rgba(245,158,11,0.5),inset_0px_1px_4px_0px_rgba(255,255,255,0.4),inset_0px_-2px_4px_0px_rgba(0,0,0,0.15)] hover:shadow-[0px_6px_28px_-4px_rgba(245,158,11,0.65),inset_0px_1px_4px_0px_rgba(255,255,255,0.5),inset_0px_-2px_4px_0px_rgba(0,0,0,0.15)]", violet: "bg-[radial-gradient(120%_80%_at_50%_70%,#8b5cf6_0%,#581c87_100%)] text-white shadow-[0px_4px_24px_-6px_rgba(139,92,246,0.5),inset_0px_1px_4px_0px_rgba(255,255,255,0.4),inset_0px_-2px_4px_0px_rgba(0,0,0,0.15)] hover:shadow-[0px_6px_28px_-4px_rgba(139,92,246,0.65),inset_0px_1px_4px_0px_rgba(255,255,255,0.5),inset_0px_-2px_4px_0px_rgba(0,0,0,0.15)]", azure: "bg-[radial-gradient(120%_80%_at_50%_70%,#0ea5e9_0%,#0369a1_100%)] text-white shadow-[0px_4px_24px_-6px_rgba(14,165,233,0.5),inset_0px_1px_4px_0px_rgba(255,255,255,0.4),inset_0px_-2px_4px_0px_rgba(0,0,0,0.15)] hover:shadow-[0px_6px_28px_-4px_rgba(14,165,233,0.65),inset_0px_1px_4px_0px_rgba(255,255,255,0.5),inset_0px_-2px_4px_0px_rgba(0,0,0,0.15)]", obsidian: "bg-[radial-gradient(120%_80%_at_50%_70%,#3f3f46_0%,#18181b_100%)] text-zinc-100 border border-white/10 shadow-[0px_4px_20px_-6px_rgba(0,0,0,0.4),inset_0px_1px_3px_0px_rgba(255,255,255,0.25),inset_0px_-2px_4px_0px_rgba(0,0,0,0.2)] hover:shadow-[0px_6px_24px_-4px_rgba(0,0,0,0.5),inset_0px_1px_3px_0px_rgba(255,255,255,0.35),inset_0px_-2px_4px_0px_rgba(0,0,0,0.2)]", pearl: "bg-[radial-gradient(120%_80%_at_50%_70%,#ffffff_0%,#e4e4e7_100%)] text-zinc-950 shadow-[0px_4px_20px_-6px_rgba(255,255,255,0.35),inset_0px_1px_3px_0px_rgba(255,255,255,0.9),inset_0px_-2px_4px_0px_rgba(0,0,0,0.08)] hover:shadow-[0px_6px_24px_-4px_rgba(255,255,255,0.45),inset_0px_1px_3px_0px_rgba(255,255,255,1),inset_0px_-2px_4px_0px_rgba(0,0,0,0.08)]", }; const sizeStyles: Record = { sm: "h-8 px-3.5 text-xs rounded-lg gap-1.5 [&_svg]:size-3.5", default: "h-10 px-5 text-sm rounded-xl gap-2 [&_svg]:size-4", lg: "h-12 px-7 text-base rounded-2xl gap-2.5 [&_svg]:size-5", icon: "size-10 p-0 rounded-xl gap-0 [&_svg]:size-4", }; export const CandyButton = React.forwardRef< HTMLElement, CandyButtonProps >( ( { as, className, children, variant = "emerald", size = "default", color, glow = true, glassSheen = true, leftIcon, rightIcon, style, disabled, ...props }, ref, ) => { const isCustom = Boolean(color); const customStyle: React.CSSProperties = isCustom ? { background: `radial-gradient(120% 80% at 50% 70%, ${color} 0%, color-mix(in srgb, ${color} 50%, black) 100%)`, boxShadow: glow ? `0px 4px 24px -6px color-mix(in srgb, ${color} 65%, transparent), inset 0px 1px 4px 0px rgba(255, 255, 255, 0.45), inset 0px -2px 4px 0px rgba(0, 0, 0, 0.15)` : `inset 0px 1px 4px 0px rgba(255, 255, 255, 0.45), inset 0px -2px 4px 0px rgba(0, 0, 0, 0.15)`, color: "#ffffff", ...style, } : (style ?? {}); const commonClass = cn( "relative inline-flex items-center justify-center font-medium leading-none tracking-[0.01em] select-none overflow-hidden cursor-pointer transition-all duration-200 ease-out active:scale-[0.98] active:brightness-95 hover:brightness-110 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-white/40 focus-visible:ring-offset-2 focus-visible:ring-offset-black disabled:pointer-events-none disabled:opacity-50 disabled:cursor-not-allowed", "after:absolute after:top-0 after:left-[15%] after:right-[15%] after:h-px after:bg-[linear-gradient(90deg,transparent,rgba(255,255,255,0.55),transparent)] after:pointer-events-none", !isCustom && variantStyles[variant], sizeStyles[size], className, ); const innerContent = ( <> {glassSheen && ( )} {leftIcon && {leftIcon}} {children} {rightIcon && {rightIcon}} ); if (as === "a" || props.href) { return ( } href={props.href} target={props.target} rel={props.rel} style={customStyle} className={commonClass} aria-disabled={disabled} role="button" {...(props as React.AnchorHTMLAttributes)} > {innerContent} ); } return ( ); }, ); CandyButton.displayName = "CandyButton"; export default CandyButton;