Modal dialog on the shared overlay runtime (focus trap, Escape/outside
dismissal, prefers-reduced-motion-aware fade).
<.modal id="confirm-delete">
<h2>Delete 3 objects?</h2>
<p>This cannot be undone.</p>
<.button phx-click={LanternUI.close_dialog("confirm-delete")}>Cancel</.button>
<.button variant="solid" color="danger" phx-click="delete">Delete</.button>
</.modal>
<.button phx-click={LanternUI.open_dialog("confirm-delete")}>Delete…</.button>The API mirrors Fluxon's modal/1; open/close from the client with
LanternUI.open_dialog/1 / close_dialog/1 (JS commands) or from the server
with LanternUI.open_dialog(socket, id) / close_dialog(socket, id).
Animation-tuning attrs (animation*) are accepted for Fluxon compatibility;
the fade duration comes from the --lantern-duration token.
The dialog is Zag-driven (a @zag-js/dialog state machine, loaded on
demand): the hook root carries data-zag plus data-scope="dialog" /
data-part anatomy, and Zag owns open state, focus trap + return, scroll
lock, Escape/outside dismissal, and initial focus. Styling stays lui-*
tokens. The server owns open via data-open (a patch asserting it
re-opens, withdrawing it closes); controlled makes the server value
strict truth with on_change fan-out.
Hand-rolled LanternModal roots without data-zag keep the legacy hook
behavior, so existing open_dialog/close_dialog call sites keep working;
new markup should use this component.
Summary
Functions
Attributes
id(:string) (required) - Stable DOM id used by open_dialog/close_dialog.open(:boolean) - render already open (server-driven modals). Defaults tofalse.on_open(Phoenix.LiveView.JS) - JS command run when the modal opens. Defaults tonil.on_close(Phoenix.LiveView.JS) - JS command run when the modal closes. Defaults tonil.class(:any) - Extra classes on the dialog panel. Defaults tonil.container_class(:any) - Extra classes on the overlay root. Defaults tonil.backdrop_class(:any) - Extra classes on the dimmed backdrop. Defaults tonil.close_on_esc(:boolean) - Close when Escape is pressed. Defaults totrue.close_on_outside_click(:boolean) - Close when the backdrop is clicked. Defaults totrue.prevent_closing(:boolean) - Block Escape and outside-click close. Defaults tofalse.hide_close_button(:boolean) - Hide the built-in close control. Defaults tofalse.role(:string) - ARIA role for the dialog panel. Defaults to"dialog".aria_label(:string) - Accessible name for the dialog panel. Defaults tonil.aria_labelledby(:string) - Id of the dialog title element. Defaults tonil.aria_describedby(:string) - Id of the dialog description element. Defaults tonil.initial_focus(:string) - Selector for the element or region that receives focus when opened. Defaults tonil.placement(:string) - Vertical panel placement within the viewport. Defaults to"center". Must be one of"center", or"top".animation(:string) - accepted for Fluxon compat; fade is token-driven. Defaults tonil.animation_enter(:string) - accepted for Fluxon compat. Defaults tonil.animation_leave(:string) - accepted for Fluxon compat. Defaults tonil.controlled(:boolean) - Strict server-driven open state:openis truth, patches flow into the machine. Defaults tofalse.on_change(:string) - Server event pushed on open change (lantern:dialog:open/closereplies). Defaults tonil.on_change_client(:string) - Bubbling DOM CustomEvent dispatched on open change. Defaults tonil.- Global attributes are accepted. Arbitrary HTML/
phx-*attributes passed through.
Slots
inner_block(required) - Dialog body content.