A single, stackable modal container for Phoenix LiveView.
One stack per page (only one modal is visible at a time). State lives in
socket.assigns.modal_stack as a %ModalStack{} struct; there is no
live_component and no hidden process.
Setup
def mount(_params, _session, socket) do
{:ok, ModalStack.attach(socket)}
endOpening / closing (from your event handlers)
ModalStack.push(socket, :confirm_delete)
ModalStack.pop(socket)
ModalStack.clear(socket)Rendering
<ModalStack.modal_stack stack={@modal_stack}>
<:modal name={:confirm_delete} on_cancel={JS.push("delete_cancelled")}>
...body...
</:modal>
</ModalStack.modal_stack>The close button, Escape, and click-away automatically pop the stack via a
hook attach/1 installs — you do not write a close handler. A slot
on_cancel (optional) runs as an extra side-effect alongside the pop.
Summary
Functions
Seeds the stack into assigns and attaches the close-event hook. Call once in
mount/3.
Close every open modal. Returns the socket.
Close the topmost modal. Returns the socket.
Open a modal by name (no-op if already open). Returns the socket.
Types
@type t() :: %ModalStack{stack: [atom()]}
Functions
Seeds the stack into assigns and attaches the close-event hook. Call once in
mount/3.
Close every open modal. Returns the socket.
Attributes
stack(ModalStack) (required)close_label(:string) - Defaults to"close".
Slots
modal(required) - Accepts attributes:name(:atom) (required)on_cancel(Phoenix.LiveView.JS)
Close the topmost modal. Returns the socket.
Open a modal by name (no-op if already open). Returns the socket.