defmodule SaladUI.Dialog do
@moduledoc """
Implement of Dialog components from https://ui.shadcn.com/docs/components/dialog
"""
use SaladUI, :component
@doc """
Dialog component
## Examples:
<.dialog :if={@live_action in [:new, :edit]} id="pro-dialog" show on_cancel={JS.navigate(~p"/p")}>
<.dialog_content class="sm:max-w-[425px]">
<.dialog_header>
<.dialog_title>Edit profile
<.dialog_description>
Make changes to your profile here click save when you're done
<.dialog_footer>
<.button type="submit">save changes
"""
attr :id, :string, required: true
attr :show, :boolean, default: false
attr :on_cancel, JS, default: %JS{}
attr :class, :string, default: nil
slot :inner_block, required: true
def dialog(assigns) do
~H"""
hide_modal(@id)}
class="relative z-50 hidden group/dialog"
>
<.focus_wrap
id={"#{@id}-wrap"}
phx-window-keydown={JS.exec("phx-hide-modal", to: "##{@id}")}
phx-key="escape"
phx-click-away={JS.exec("phx-hide-modal", to: "##{@id}")}
class="w-full sm:max-w-[425px]"
>
{render_slot(@inner_block)}
Close
"""
end
attr :class, :string, default: nil
slot :inner_block, required: true
def dialog_header(assigns) do
~H"""
{render_slot(@inner_block)}
"""
end
attr :class, :string, default: nil
slot :inner_block, required: true
def dialog_title(assigns) do
~H"""
{render_slot(@inner_block)}
"""
end
attr :class, :string, default: nil
slot :inner_block, required: true
def dialog_description(assigns) do
~H"""
{render_slot(@inner_block)}
"""
end
attr :class, :string, default: nil
slot :inner_block, required: true
def dialog_footer(assigns) do
~H"""
{render_slot(@inner_block)}
"""
end
def show_modal(js \\ %JS{}, id) when is_binary(id) do
js
|> JS.set_attribute({"data-state", "open"}, to: "##{id}")
|> JS.show(to: "##{id}", transition: {"_", "_", "_"}, time: 130)
|> JS.add_class("overflow-hidden", to: "body")
|> JS.focus_first(to: "##{id}-content")
end
def hide_modal(js \\ %JS{}, id) do
js
|> JS.set_attribute({"data-state", "closed"}, to: "##{id}")
|> JS.hide(to: "##{id}", transition: {"_", "_", "_"}, time: 130)
|> JS.remove_class("overflow-hidden", to: "body")
|> JS.pop_focus()
end
end