{{--
ShiftBridge Button Component
Usage:
Default
Primary
Secondary
Success
Danger
Outline Primary
Ghost
Small
Large
Disabled
Loading
With Icon
Icon Right
Props:
- variant: string (default, primary, secondary, success, danger, warning, info, outline-primary, outline-secondary, outline-success, outline-danger, ghost)
- size: string (sm, md, lg)
- disabled: boolean
- loading: boolean
- icon: string (Lucide icon name)
- iconPosition: string (left, right)
- type: string (button, submit, reset)
- href: string (renders as anchor tag if provided)
--}}
@props([
'variant' => 'primary',
'size' => 'md',
'disabled' => false,
'loading' => false,
'icon' => null,
'iconPosition' => 'left',
'type' => 'button',
'href' => null,
])
@php
// Base classes - always applied
$baseClasses = 'inline-flex items-center justify-center gap-2 font-medium transition-all duration-150 ease-in-out focus:outline-none focus:ring-2 focus:ring-offset-1';
// Size classes
$sizeClasses = match($size) {
'sm' => 'px-3 py-1.5 text-sm rounded', // 4px radius
'md' => 'px-4 py-2 text-sm rounded-md', // 6px radius
'lg' => 'px-6 py-3 text-base rounded-lg', // 8px radius
default => 'px-4 py-2 text-sm rounded-md',
};
// Variant classes - using design tokens
$variantClasses = match($variant) {
'primary' => 'bg-[var(--sb-primary)] text-white hover:bg-[var(--sb-primary-dark)] focus:ring-[var(--sb-primary)] shadow-sm',
'secondary' => 'bg-[var(--sb-text-secondary)] text-white hover:bg-slate-600 focus:ring-slate-400 shadow-sm',
'success' => 'bg-[var(--sb-success)] text-white hover:bg-green-600 focus:ring-[var(--sb-success)] shadow-sm',
'danger' => 'bg-[var(--sb-danger)] text-white hover:bg-red-600 focus:ring-[var(--sb-danger)] shadow-sm',
'warning' => 'bg-[var(--sb-warning)] text-white hover:bg-amber-600 focus:ring-[var(--sb-warning)] shadow-sm',
'info' => 'bg-[var(--sb-info)] text-white hover:bg-cyan-600 focus:ring-[var(--sb-info)] shadow-sm',
'outline-primary' => 'border-2 border-[var(--sb-primary)] text-[var(--sb-primary)] hover:bg-[var(--sb-primary)] hover:text-white focus:ring-[var(--sb-primary)]',
'outline-secondary' => 'border-2 border-[var(--sb-text-secondary)] text-[var(--sb-text-secondary)] hover:bg-[var(--sb-text-secondary)] hover:text-white focus:ring-slate-400',
'outline-success' => 'border-2 border-[var(--sb-success)] text-[var(--sb-success)] hover:bg-[var(--sb-success)] hover:text-white focus:ring-[var(--sb-success)]',
'outline-danger' => 'border-2 border-[var(--sb-danger)] text-[var(--sb-danger)] hover:bg-[var(--sb-danger)] hover:text-white focus:ring-[var(--sb-danger)]',
'ghost' => 'text-[var(--sb-text-secondary)] hover:bg-slate-100 hover:text-[var(--sb-text-primary)] focus:ring-slate-300',
'default' => 'bg-[var(--sb-card-header-bg)] border border-[var(--sb-border)] text-[var(--sb-text-primary)] hover:bg-slate-200 focus:ring-slate-300',
default => 'bg-[var(--sb-primary)] text-white hover:bg-[var(--sb-primary-dark)] focus:ring-[var(--sb-primary)] shadow-sm',
};
// State classes
$stateClasses = '';
if ($disabled || $loading) {
$stateClasses = 'opacity-60 cursor-not-allowed pointer-events-none';
}
// Combine all classes
$classes = implode(' ', array_filter([$baseClasses, $sizeClasses, $variantClasses, $stateClasses]));
// Icon SVG mapping (Lucide icons)
$iconSvg = match($icon) {
'plus' => '',
'trash' => '',
'edit' => '',
'save' => '',
'cancel' => '',
'search' => '',
'refresh' => '',
'arrow-left' => '',
'arrow-right' => '',
'download' => '',
'upload' => '',
'filter' => '',
'settings' => '',
'user' => '',
'phone' => '',
'log-out' => '',
default => null,
};
// Loading spinner SVG
$loadingSvg = '';
@endphp
@if($href)
merge(['class' => $classes]) }}>
@if($loading)
{!! $loadingSvg !!}
@elseif($icon && $iconPosition === 'left')
{!! $iconSvg !!}
@endif
{{ $slot }}
@if($icon && $iconPosition === 'right' && !$loading)
{!! $iconSvg !!}
@endif
@else
@endif