Installation
composer require wire-elements/modal
Publish the package assets (if needed):
php artisan vendor:publish --tag=modal-assets
Include the Livewire Directive
Add this to your main layout file (e.g., resources/views/layouts/app.blade.php):
@livewire('livewire-ui-modal')
First Modal Usage Trigger a modal from a button click:
<button wire:click="$emit('open-modal', 'confirmation-modal')">
Open Modal
</button>
<!-- Modal Definition (in a Livewire component) -->
<livewire:confirmation-modal />
Define a Modal Component
Create a Livewire component (e.g., ConfirmationModal):
namespace App\Http\Livewire;
use Livewire\Component;
class ConfirmationModal extends Component
{
public $name = 'confirmation-modal';
public function render()
{
return view('livewire.confirmation-modal');
}
}
<!-- resources/views/livewire/confirmation-modal.blade.php -->
<div class="modal-content">
<h2>Confirm Action</h2>
<p>Are you sure you want to proceed?</p>
<button wire:click="$emit('close-modal')">Cancel</button>
<button wire:click="$emit('confirm-action')">Confirm</button>
</div>
Modal Triggering
Use $emit('open-modal', 'modal-name') to open a modal from any Livewire component or Blade view.
<button wire:click="$emit('open-modal', 'edit-profile-modal')">
Edit Profile
</button>
Nested Modals
Supports stacking modals by emitting open-modal from within another modal’s component:
<button wire:click="$emit('open-modal', 'nested-modal')">
Open Nested
</button>
Modal State Management Use Livewire properties to manage modal-specific state:
public $isOpen = false;
public $formData = [];
public function mount()
{
$this->isOpen = false;
}
public function openModal()
{
$this->isOpen = true;
}
Dynamic Modal Content
Pass data via $emit or Livewire properties:
<button wire:click="$emit('open-modal', 'user-modal', { userId: 123 })">
View User
</button>
Capture data in the modal component:
protected $listeners = ['open-modal' => 'handleOpen'];
public function handleOpen($modalName, $data = [])
{
if ($modalName === $this->name) {
$this->userId = $data['userId'] ?? null;
}
}
Closing Modals
Use $emit('close-modal') to close the current modal or $emit('close-all-modals') to close all.
<form wire:submit="save">
<input type="text" wire:model="name">
<button type="submit">Save</button>
</form>
@if($this->isOpen)
<livewire:my-modal />
@endif
Modal Registration
@livewire('livewire-ui-modal') is included in your layout file after the opening <body> tag.State Persistence
protected $persistent = ['modalData'];
Nested Modal Conflicts
Event Listener Overrides
$emit('open-modal') not triggering the correct modal.$name property matches the emitted name exactly.CSS Conflicts
php artisan vendor:publish --tag=modal-assets --force
open-modal are firing:
document.addEventListener('livewire:emit', (e) => {
console.log('Event:', e.detail);
});
config/livewire.php:
'log' => env('LIVEWIRE_LOG', true),
Reusable Modal Components Create a base modal component and extend it for specific use cases:
class BaseModal extends Component
{
public $name;
public $isOpen = false;
public function mount($name)
{
$this->name = $name;
}
public function open()
{
$this->isOpen = true;
}
}
Modal Stack Management Track the modal stack in a parent component:
public $modalStack = [];
protected $listeners = [
'open-modal' => 'pushToStack',
'close-modal' => 'popFromStack',
];
public function pushToStack($modalName)
{
$this->modalStack[] = $modalName;
}
public function popFromStack()
{
array_pop($this->modalStack);
}
Accessibility Ensure modals are keyboard-navigable and screen-reader friendly:
<div wire:ignore class="modal" role="dialog" aria-modal="true">
<!-- Modal content -->
</div>
Performance
Lazy-load modal components or use wire:ignore for non-interactive elements to reduce initial load time.
Testing Test modal interactions with Livewire’s testing utilities:
$this->emit('open-modal', 'test-modal');
$this->assertSeeInLivewire('modal-content');
How can I help you explore Laravel packages today?