{{--
Form Button — shadcn-style variants; sizes match x-buttons.primary / x-buttons.secondary.
Variants: default | destructive | outline | secondary | ghost | link
Sizes: sm | md | lg | icon (+ legacy: default → md)
Variant legacy: primary→default, danger→destructive
--}}
@props([
'variant' => 'default',
'size' => 'md',
'type' => 'button',
'href' => null,
'loading' => false,
])
@php
$variant = match ($variant) {
'primary' => 'default',
'danger' => 'destructive',
default => $variant,
};
$size = match ($size) {
'default' => 'md',
default => $size,
};
$base = 'inline-flex cursor-pointer select-none items-center justify-center gap-2 whitespace-nowrap font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-60';
$variantClass = match ($variant) {
'destructive' =>
'bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90 focus-visible:ring-destructive',
'outline' =>
'border border-input bg-background text-foreground shadow-sm hover:bg-muted hover:text-foreground focus-visible:ring-ring',
'secondary' =>
'bg-muted text-foreground shadow-sm hover:bg-muted/80 focus-visible:ring-ring',
'ghost' =>
'text-foreground hover:bg-muted hover:text-foreground focus-visible:ring-ring',
'link' =>
'text-primary-600 underline-offset-4 hover:underline focus-visible:ring-ring dark:text-primary-400',
default =>
'bg-brand text-brand-foreground shadow-sm hover:bg-brand/90 active:bg-brand/80 focus-visible:ring-ring dark:focus-visible:ring-offset-background',
};
$sizeClass = match ($variant) {
'link' => match ($size) {
'sm' => 'h-auto rounded-none px-0 py-0 text-xs',
'lg' => 'h-auto rounded-none px-0 py-0 text-base',
default => 'h-auto rounded-none px-0 py-0 text-sm',
},
default => match ($size) {
'sm' => 'gap-1.5 rounded-md px-2.5 py-1.5 text-2xs [&_svg]:size-3.5 sm:gap-2 sm:px-3 sm:py-1.5 sm:text-xs sm:[&_svg]:size-4',
'lg' => 'gap-2 rounded-lg px-4 py-2.5 text-sm [&_svg]:size-4 sm:gap-2.5 sm:rounded-xl sm:px-5 sm:py-3 sm:text-base sm:[&_svg]:size-5 md:px-6 md:py-3.5',
default => 'gap-2 rounded-lg px-3.5 py-2 text-xs [&_svg]:size-4 sm:px-4 sm:py-2 sm:text-sm',
},
};
// Link variant: no shadow / border noise from utilities that might leak via merge
$linkExtras = $variant === 'link' ? ' shadow-none border-transparent bg-transparent hover:bg-transparent dark:hover:bg-transparent' : '';
$classes = trim("$base $variantClass $sizeClass $linkExtras");
@endphp
@if ($href)
merge(['class' => $classes]) }}>
@if ($loading)
@endif
{{ $slot }}
@else
@endif