ModalStack
A single, stackable modal container for Phoenix LiveView. One stack per page —
only one modal is visible at a time — built on a struct in assigns + a function
component + a LiveView hook (no live_component, no hidden process).
Installation
def deps do
[{:modal_stack, "~> 0.1"}]
end
Tailwind
The default chrome ships Tailwind utility classes, so your app must include the
package in its Tailwind content scan. For Tailwind v4, add to your app.css:
@source "../../deps/modal_stack/lib";
(Adjust the relative path to point at deps/modal_stack/lib from your CSS file.)
Usage
def mount(_params, _session, socket) do
{:ok, ModalStack.attach(socket)}
end
def handle_event("delete", _p, socket), do: {:noreply, ModalStack.push(socket, :confirm_delete)}
<ModalStack.modal_stack stack={@modal_stack}>
<:modal name={:confirm_delete} on_cancel={JS.push("delete_cancelled")}>
<p>Are you sure?</p>
<.button phx-click="really_delete">Delete</.button>
</:modal>
</ModalStack.modal_stack>
The close button, Escape, and click-away pop the stack automatically — no
close handler needed. on_cancel is an optional extra side-effect.
API
ModalStack.attach(socket)— seed state + hook (call inmount/3)ModalStack.push(socket, name)— open a modal (atom name; dedups)ModalStack.pop(socket)— close the topmostModalStack.clear(socket)— close all