Livewire 3 + Aura UI: The Perfect Match
Two Libraries, One Philosophy
Livewire 3 and Aura UI share a core belief: Laravel developers should not need to learn a JavaScript framework to build modern, interactive interfaces. Livewire handles reactivity and server communication. Aura UI handles the visual layer. Together, they let you build applications that feel like SPAs without leaving PHP.
How They Work Together
Every Aura UI component is a standard Blade component. This means you can use wire:model, wire:click, and every other Livewire directive directly on them:
{{-- In a Livewire component view --}}
<x-aura::input
label="Search"
wire:model.live.debounce.300ms="search"
placeholder="Search users..."
icon="magnifying-glass"
/>
<x-aura::select label="Role" wire:model="role">
<option value="">All Roles</option>
<option value="admin">Admin</option>
<option value="editor">Editor</option>
<option value="viewer">Viewer</option>
</x-aura::select>
The wire:model.live directive makes the search input reactive. As the user types, Livewire sends requests to the server, your component filters the data, and the results update in real time.
Building a Live Search Component
Here is a complete example of a user search built with Livewire 3 and Aura UI:
// app/Livewire/UserSearch.php
class UserSearch extends Component
{
public string $search = '';
public string $role = '';
public function render()
{
$users = User::query()
->when($this->search, fn ($q) => $q->where('name', 'like', "%{$this->search}%"))
->when($this->role, fn ($q) => $q->where('role', $this->role))
->paginate(10);
return view('livewire.user-search', compact('users'));
}
}
{{-- resources/views/livewire/user-search.blade.php --}}
<div class="space-y-6">
<div class="flex gap-4">
<x-aura::input
wire:model.live.debounce.300ms="search"
placeholder="Search by name..."
icon="magnifying-glass"
class="flex-1"
/>
<x-aura::select wire:model.live="role" class="w-48">
<option value="">All Roles</option>
<option value="admin">Admin</option>
<option value="editor">Editor</option>
</x-aura::select>
</div>
<div class="grid gap-4">
@forelse($users as $user)
<x-aura::card>
<x-aura::card.body class="flex items-center gap-4">
<x-aura::avatar :src="$user->avatar_url" :alt="$user->name" />
<div>
<p class="font-semibold">{{ $user->name }}</p>
<p class="text-sm text-gray-500">{{ $user->email }}</p>
</div>
<x-aura::badge class="ml-auto">{{ $user->role }}</x-aura::badge>
</x-aura::card.body>
</x-aura::card>
@empty
<x-aura::alert variant="info">No users found.</x-aura::alert>
@endforelse
</div>
{{ $users->links() }}
</div>
This gives you a fully reactive search with filtering, avatars, badges, and cards -- all without writing any JavaScript.
Loading States
Aura UI buttons work seamlessly with Livewire loading states:
<x-aura::button wire:click="save" wire:loading.attr="disabled">
<span wire:loading.remove>Save Changes</span>
<span wire:loading>Saving...</span>
</x-aura::button>
You can also use the button's built-in loading prop with Alpine.js for instant feedback.
Best Practices
- Use
wire:model.live.debounceon search inputs to avoid excessive requests - Combine Livewire reactivity with Aura UI feedback components (alerts, toasts) for user notifications
- Keep Livewire components focused -- one component per interactive section
- Use Aura UI modal with Livewire events for confirm dialogs and forms
Livewire 3 and Aura UI are the modern TALL stack done right. No build step for interactivity, no context switching between PHP and JavaScript, and a consistent, beautiful UI across your entire application.