Wirestrap is still in active development
This project is pre-1.0 and may introduce breaking changes at any time without prior notice.
Modal
Modal dialog built on Alpine.js. Open and close via the $wirestrap.modal Alpine magic
helper, or programmatically from Livewire via the WithWirestrap trait.
Supports dragging, minimizing to a taskbar, fullscreen expand, resize handles, static mode,
backdrop overlay, and automatic z-index stacking for simultaneously open modals.
Basic usage
Call $wirestrap.modal.show(id) from any Alpine context to open a modal.
A modal can be closed four ways: the close button (when dismissible),
pressing Escape, clicking outside the dialog, or any element with
data-ws-dismiss="modal" inside the modal.
<button x-on:click="$wirestrap.modal.show('contact-modal')">Add contact</button>
<x-wirestrap::modal id="contact-modal" title="Add contact" backdrop>
<x-wirestrap::input label="Name" wire:model="name" />
<x-wirestrap::input label="Email" type="email" wire:model="email" />
<x-slot:footer>
<button data-ws-dismiss="modal">Cancel</button>
<button wire:click="save">Save</button>
</x-slot:footer>
</x-wirestrap::modal>
Static mode
Pass static to prevent closing on outside click or Escape: the dialog shakes
instead. The close button and data-ws-dismiss elements still work normally.
Pair it with backdrop for the full effect.
<x-wirestrap::modal ... static>
...
</x-wirestrap::modal>
Draggable
The draggable prop lets the modal be repositioned by dragging its header,
on both mouse and touch. Body scroll is not locked, so multiple draggable modals can be
open and interacted with simultaneously.
<x-wirestrap::modal ... draggable>
...
</x-wirestrap::modal>
Expandable & resizable
Add expandable to show a fullscreen toggle button in the header; clicking it
fills the viewport and restores on the next click. Add resizable to expose drag
handles on the east, west, south, and corner edges. Both work with draggable.
The width cannot be reduced below the modal's natural width; the height can go down to the header.
<x-wirestrap::modal ... resizable expandable>
...
</x-wirestrap::modal>
Minimizable
Add minimizable to show a minimize button that collapses the modal to a restore
button in a shared taskbar. The button label comes from the title prop, or from
the id if no title is set.
<x-wirestrap::modal ... minimizable>
...
</x-wirestrap::modal>
The taskbar container is auto-created as #minimized_modals and appended to
<body>. Place a <div id="minimized_modals"> anywhere
in your layout to control its position.
{{-- Auto-created if absent. Place it in your layout to control its position. --}}
<div id="minimized_modals"></div>
Stacking
Multiple modals can be open simultaneously. Each one gets a z-index one step above the current highest. Escape closes only the topmost open modal.
Open all three and play around: drag them, resize, minimize, go fullscreen.
<x-wirestrap::modal id="modal-1" title="Notes" draggable minimizable resizable expandable> ... </x-wirestrap::modal>
<x-wirestrap::modal id="modal-2" title="Editor" draggable minimizable resizable expandable> ... </x-wirestrap::modal>
<x-wirestrap::modal id="modal-3" title="Preview" draggable minimizable resizable expandable> ... </x-wirestrap::modal>
ModalManager
ModalManager is a Livewire component that injects other Livewire components
inside modals at runtime. The modal lives in the layout, outside any stacking context,
which avoids issues with modals inside tabs (display: none), nested z-index
contexts, or modals that need to survive component re-renders.
Place it once in your layout:
{{-- In your app layout, once --}}
<livewire:wirestrap.modal-manager />
In any Livewire component, add the WithWirestrap trait and call
modalShowManaged. The modalProps array accepts the same props
as x-wirestrap::modal (title, size,
draggable, etc.).
use Wirestrap\Traits\WithWirestrap;
class UserList extends Component
{
use WithWirestrap;
public function edit(int $userId): void
{
$this->modalShowManaged(
component: 'users.edit-form',
props: ['userId' => $userId],
modalProps: ['title' => 'Edit user', 'size' => '800'],
);
}
}
The child Livewire component automatically receives a $modalId prop. Use it
with modalHide to close the modal from PHP after an action completes.
class EditForm extends Component
{
use WithWirestrap;
public string $modalId;
public int $userId;
public function save(): void
{
// ...
$this->modalHide($this->modalId);
}
}
Calls with the same component + props + modalProps
combination re-show the already-injected modal instead of creating a duplicate.
Use modalDestroyManaged to remove injected modals:
by component type, by an explicit key, or all at once.
Both component and key accept a string or an array of strings,
so multiple modals can be destroyed in a single dispatch.
// Remove all managed modals
$this->modalDestroyManaged();
// Remove all modals for a specific component type
$this->modalDestroyManaged(component: 'users.edit-form');
// Remove multiple component types at once
$this->modalDestroyManaged(component: ['users.edit-form', 'users.view-form']);
// Remove a modal by key (requires key when opening)
$this->modalShowManaged(..., key: 'edit-user-' . $userId);
$this->modalDestroyManaged(key: 'edit-user-' . $userId);
// Remove multiple modals in a single dispatch
$this->modalDestroyManaged(key: ['edit-user-5', 'edit-user-12', 'edit-user-37']);
Props
Global configuration
Most prop defaults can be overridden globally via config/wirestrap.php.
x-wirestrap::modal
| Prop | Type | Default | Description |
|---|---|---|---|
id |
string|null |
null |
Element id. Required when strict mode is enabled. |
title |
ComponentSlot|string|null |
null |
Header title text or slot. |
footer |
ComponentSlot|string|null |
null |
Footer content. Use x-slot:footer for multiple elements. |
size |
string|null |
config |
Sets the dialog width via ws-modal-{size}. Accepts values from 300 to 1900 in steps of 100 (e.g. 400, 800, 1200). Always capped at the viewport width. |
dismissible |
bool |
config |
Show the close button in the header. |
static |
bool |
config |
Shake instead of closing on outside click or Escape. |
backdrop |
bool |
config |
Show a backdrop overlay behind the modal. |
draggable |
bool |
config |
Allow dragging the dialog by its header. Does not lock body scroll. |
minimizable |
bool |
config |
Show a minimize button that collapses the modal to a taskbar button. |
expandable |
bool |
config |
Show a fullscreen toggle button in the header. |
resizable |
bool |
config |
Show resize handles on the east, west, south, south-east, and south-west edges. |
|
No results found
|
|||
$wirestrap.modal
| Method | Type | Default | Description |
|---|---|---|---|
$wirestrap.modal.show(id) |
-- |
-- |
Show the modal with the given id. |
$wirestrap.modal.hide(id) |
-- |
-- |
Hide the modal with the given id. |
|
No results found
|
|||