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