Dialogs: centred modal, full-screen modal, and slide-over panel.
Ports Pines modal, full screen modal and slide-over. All three share one open/close contract.
<.button x-on:click="$dispatch('pine:open', {}, {target: document.getElementById('confirm')})">
Delete
</.button>
<.modal id="confirm" title="Are you sure?">
This cannot be undone.
<:footer><.button variant="destructive">Delete</.button></:footer>
</.modal>Opening and closing from the server
Every dialog listens for three namespaced events on itself, so no JavaScript is needed:
<.button phx-click={JS.dispatch("pine:open", to: "#confirm")}>Delete</.button>pine:open, pine:close and pine:toggle are all understood. Scoping them to the
element rather than window means several dialogs coexist without the id-matching dance
that a global listener would need.
From a LiveView, push through the PineBridge hook:
push_event(socket, "pine:dispatch", %{to: "#confirm", event: "pine:close"})Focus trapping
x-trap.noscroll requires the Alpine Focus
plugin. Without it the dialog still opens and closes,
but focus can escape to the page behind and background scrolling is not locked — so
install it if you use dialogs.