Components
Modals
Modals
Modals sit on top of an applications main window and require a live view to handle their on/off state. We recommend using a new route to map to the on/off state.
Sizes
Router
scope "/", PetalProWeb do
pipe_through [:browser]
live "/", ExampleLive, :index
live "/modal", ExampleLive, :modal
end
Live view/component
defmodule ExampleLive do
use PetalProWeb, :live_view
# ...
@impl true
def handle_params(params, _uri, socket) do
{:noreply, socket}
end
# The modal component emits this event when `PetalComponents.Modal.hide_modal()` is called.
# This happens when the user clicks the dark background or the 'X'.
@impl true
def handle_event("close_modal", _, socket) do
# Go back to the :index live action
{:noreply, push_patch(socket, to: "/")}
end
# ...
end
HEEX template
<.a type="live_patch" to="/modal" label="Opens the modal" />
<%= if @live_action == :modal do %>
<.modal max_width="sm|md|lg|xl|2xl|full" title="Modal">
<.p>Content</.p>
<div class="flex justify-end">
<.button label="close" phx-click={PetalComponents.Modal.hide_modal()} />
</div>
</.modal>
<% end %>
Close modal target
If you’re nesting a modal inside a live component, the close event will go to the parent live view, instead of the component.
To fix this, you can change the target to be the live component:
<.modal title="Modal" close_modal_target={@myself}>
<.p>Content</.p>
</.modal>
Underneath the hood, this gets forwarded to the JS.push
function. Here’s what it looks like:
# in petal_components/modal.ex
JS.push(js, "close_modal", target: close_modal_target)
Properties
Defaults are indicated in bold. Required fields have * before the label. Hover over the name for docs.
Name | Type | Options/Default |
---|---|---|
title | :string | - |
size | :string | "sm", "md", "lg", "xl", "2xl", "full" |
class | :string | - |
close_modal_target | :string | - |
inner_block* | :slot | - |
[all additional properties] | Unused. |