@props([ 'tag' => 'button', 'href' => null, 'type' => 'button', 'size' => 'lg', 'variant' => 'primary', 'position' => 'relative', ]) @php $tag = $href ? 'a' : $tag; $sizeClasses = match($size) { 'sm' => 'py-2 px-6 text-sm', 'md' => 'py-3.5 px-6 text-base', default => 'py-5 px-[46px] text-[19px]', }; // 'primary' is the CTA look (offset-shadow via .btn-primary's ::before/ // ::after, italic, uppercase). 'secondary' is a plain bordered toggle — // no shadow layers, fills solid on hover/aria-pressed=true instead, used // for option pickers (see x-ui.option-buttons) and anywhere else a // secondary/toggle action shouldn't compete visually with the CTA. $variantClasses = match($variant) { 'secondary' => 'font-semibold hover:bg-black hover:text-neutral-200 aria-pressed:bg-black aria-pressed:text-neutral-200 transition-colors focus:outline-none focus-visible:ring-2 focus-visible:ring-black', default => 'btn-primary font-bold italic uppercase', }; // $position defaults to 'relative' (needed so the ::before/::after layers // in .btn-primary position against the button itself), but callers that // need to place the button absolutely (e.g. a hover-reveal CTA over a // product image) must pass position="absolute" here rather than adding // "absolute" via the class prop — Tailwind's generated stylesheet always // orders the "relative" utility after "absolute", so on a class clash // "relative" silently wins and the button never actually gets positioned. $class = trim($position.' isolate inline-flex items-center justify-center border border-black text-black cursor-pointer no-underline disabled:cursor-not-allowed disabled:opacity-50 '.$variantClasses.' '.$sizeClasses); $attrs = $href ? $attributes->merge(['href' => $href, 'class' => $class]) : $attributes->merge(['type' => $type, 'class' => $class]); @endphp <{{ $tag }} {{ $attrs }}> {{ $slot }}