label('Save')->primary() * Button::make()->label('Cancel')->secondary()->href('/back') */ class Button extends Component { protected string $label = ''; protected ?string $href = null; protected string $type = 'button'; protected string $variant = 'primary'; protected string $size = 'md'; protected bool $disabled = false; /** * Set the button label. */ public function label(string $label): static { $this->label = $label; return $this; } /** * Make this a link button. */ public function href(string $href): static { $this->href = $href; return $this; } /** * Set the button type (button, submit, reset). */ public function type(string $type): static { $this->type = $type; return $this; } /** * Set to submit type. */ public function submit(): static { return $this->type('submit'); } /** * Primary variant (default). */ public function primary(): static { $this->variant = 'primary'; return $this; } /** * Secondary variant. */ public function secondary(): static { $this->variant = 'secondary'; return $this; } /** * Danger variant. */ public function danger(): static { $this->variant = 'danger'; return $this; } /** * Ghost variant (minimal styling). */ public function ghost(): static { $this->variant = 'ghost'; return $this; } /** * Set size (sm, md, lg). */ public function size(string $size): static { $this->size = $size; return $this; } /** * Small size. */ public function sm(): static { return $this->size('sm'); } /** * Large size. */ public function lg(): static { return $this->size('lg'); } /** * Disable the button. */ public function disabled(bool $disabled = true): static { $this->disabled = $disabled; return $this; } /** * Get variant CSS classes. */ protected function variantClasses(): string { return match ($this->variant) { 'primary' => 'bg-zinc-900 text-white hover:bg-zinc-800 dark:bg-white dark:text-zinc-900 dark:hover:bg-zinc-100', 'secondary' => 'bg-zinc-100 text-zinc-900 hover:bg-zinc-200 dark:bg-zinc-700 dark:text-white dark:hover:bg-zinc-600', 'danger' => 'bg-red-600 text-white hover:bg-red-700', 'ghost' => 'text-zinc-600 hover:bg-zinc-100 dark:text-zinc-400 dark:hover:bg-zinc-800', default => '', }; } /** * Get size CSS classes. */ protected function sizeClasses(): string { return match ($this->size) { 'sm' => 'px-2.5 py-1.5 text-sm', 'lg' => 'px-5 py-3 text-lg', default => 'px-4 py-2', }; } /** * Render the button to HTML. */ public function render(): string { $baseClasses = [ 'inline-flex', 'items-center', 'justify-center', 'gap-2', 'rounded-md', 'font-medium', 'transition-colors', 'focus:outline-none', 'focus:ring-2', 'focus:ring-offset-2', ]; if ($this->disabled) { $baseClasses[] = 'opacity-50'; $baseClasses[] = 'cursor-not-allowed'; } $classes = array_merge( $baseClasses, explode(' ', $this->variantClasses()), explode(' ', $this->sizeClasses()) ); // Link button if ($this->href !== null) { $attrs = $this->buildAttributes($classes); return ''.e($this->label).''; } // Button element if ($this->disabled) { $this->attr('disabled', true); } $this->attr('type', $this->type); $attrs = $this->buildAttributes($classes); return ''.e($this->label).''; } }