Livewire
Slate works with Laravel Livewire out of the box — wire:model, validation errors, loading states, and Alpine overlays all play nicely together.
Installation
composer require livewire/livewire
composer require electrik/slate
Buttons and actions
{{-- resources/views/livewire/counter.blade.php --}}
<div>
<x-slate::button wire:click="increment">
Count: {{ $count }}
</x-slate::button>
</div>
Form controls
Progressive props (label, description, errorMessage) compose the field helpers automatically. Livewire validation keys are detected from wire:model / name.
<form wire:submit="save" class="grid max-w-md gap-4">
<x-slate::input
label="Name"
wire:model="name"
description="How you appear on invoices."
/>
<x-slate::textarea
label="Bio"
wire:model.blur="bio"
/>
<x-slate::select label="Country" wire:model="country">
<option value="us">United States</option>
<option value="uk">United Kingdom</option>
</x-slate::select>
<x-slate::checkbox
label="Subscribe"
description="Product updates only."
wire:model="subscribe"
/>
<x-slate::button type="submit" wire:loading.attr="disabled">
<span wire:loading.remove>Save</span>
<span wire:loading>Saving…</span>
</x-slate::button>
</form>
Or let Slate handle the busy UI when you use wire:click / wire:submit with loading-text:
<x-slate::button wire:click="save" loading-text="Saving…">
Save
</x-slate::button>
For static docs demos (no Livewire), use the loading prop or Alpine — see Button.
Toast from Livewire
Mount <x-slate::toaster /> once in your layout, then dispatch a browser event after an action:
// app/Livewire/ProfileForm.php
public function save(): void
{
$this->validate();
// ...
$this->dispatch('slate-toast',
title: 'Saved',
description: 'Your profile was updated.',
variant: 'success',
);
}
Livewire v3 browser events bubble as slate-toast with a detail payload — the toaster listens on window.
You can also listen in Alpine:
<div @@slate-toast.window="console.log($event.detail)">
…
</div>
Dialogs and sheets
Keep Alpine state on the Slate root; call Livewire from actions inside:
<x-slate::dialog>
<x-slate::dialog-trigger>
<x-slate::button variant="outline">Delete account</x-slate::button>
</x-slate::dialog-trigger>
<x-slate::dialog-content title="Are you sure?" description="This cannot be undone.">
<x-slot:footer>
<x-slate::dialog-close>
<x-slate::button variant="outline">Cancel</x-slate::button>
</x-slate::dialog-close>
<x-slate::button variant="destructive" wire:click="delete">
Delete
</x-slate::button>
</x-slot:footer>
</x-slate::dialog-content>
</x-slate::dialog>
Best practices
- Prefer
wire:model/wire:model.live/wire:model.bluron Slate controls — error wiring is automatic. - Put one
toasterin the layout; fireslate-toastfrom components or Alpine. - Don’t nest Alpine
x-dataroots that fight Livewire morphing on the same node aswire:*. - Use
wire:loadingon buttons/spinners for submit feedback.