Modal

A fully-managed dialog component with accessibility features and smooth transitions. Modals can be loaded asynchronously from the server, integrated with forms, and paired with live navigation for deep linking capabilities.

Body scrolling is automatically prevented when modals are open and focus is trapped within the modal to ensure users stay focused on the modal content.

Quick Start

The most basic modal requires just a trigger button and three components: .modal, .modal_overlay, and .modal_panel.

Call Prima.Modal.open("modal-id") to show the modal. For simple modals with no asynchronous fetching, the open/closed state is fully managed by Prima.

Advanced Usage

Async Loading

Asynchronous modals enable server-side data fetching before displaying content, providing a smooth user experience for dynamic modal content. This pattern is ideal when you need to load user-specific data, perform database queries, or fetch content that depends on user actions.

The async modal pattern uses a two-phase approach. Initially, only the modal backdrop and loading spinner are shown via .modal_loader. The actual modal content in .modal_panel is rendered conditionally based on the liveview assigns once the async loading operation is complete.

To implement async modals, your trigger button needs a phx-click event that pushes to your LiveView (e.g., JS.push("load-modal-data")) in addition to calling Prima.Modal.open("modal-id"). The modal component requires an on_close handler to synchronize the closed state with your LiveView.

In your LiveView's handle_event, perform your async operations (database queries, API calls, etc.) and render the modal content conditionally after updating the liveview assigns.

This pattern works particularly well for edit forms, detail views, confirmation dialogs with dynamic content, and any scenario where modal content depends on server-side state or computations.

Form Integration

Modals work seamlessly with Phoenix forms, validation, and submission handling.

Use the on_close attribute to chain JavaScript commands with LiveView events for backend state synchronization.

Browser History

Integrate modals with browser navigation for bookmarkable and shareable modal states.

When integrated with Phoenix LiveView routing, modals respond to URL changes and update the browser's address bar.

# In your router.ex
live "/", DemoLive, :index
live "/modal/history", DemoLive, :modal_history
# In your LiveView module
def handle_params(_params, _url, socket) do
case socket.assigns.live_action do
:modal_history ->
{:noreply, assign(socket, show_history_modal: true)}
_ ->
{:noreply, assign(socket, show_history_modal: false)}
end
end