live_beats/lib/live_beats_web/live/layout_component.ex
Chris McCord 819d5ecc98 Add accessible modal with focus_wrap component
The focus_wrap function component (and hook) can
be used to focus wrap any content.

The focus and focus_closest JS functions were added to
programmtaically focus an element on the client or
find the next element or previous element sibling when an
action is taken that requires moving focus to cloest item.

Co-authored-by: Nolan Darilek <nolan@thewordnerd.info>
2022-02-04 11:48:05 -05:00

55 lines
1.5 KiB
Elixir

defmodule LiveBeatsWeb.LayoutComponent do
@moduledoc """
Component for rendering content inside layout without full DOM patch.
"""
use LiveBeatsWeb, :live_component
def show_modal(module, attrs) do
send_update(__MODULE__, id: "layout", show: Enum.into(attrs, %{module: module}))
end
def hide_modal do
send_update(__MODULE__, id: "layout", show: nil)
end
def update(%{id: id} = assigns, socket) do
show =
case assigns[:show] do
%{module: _module, confirm: {text, attrs}} = show ->
show
|> Map.put_new(:title, show[:title])
|> Map.put_new(:on_cancel, show[:on_cancel] || %JS{})
|> Map.put_new(:on_confirm, show[:on_confirm] || %JS{})
|> Map.put_new(:patch, nil)
|> Map.put_new(:navigate, nil)
|> Map.merge(%{confirm_text: text, confirm_attrs: attrs})
nil ->
nil
end
{:ok, assign(socket, id: id, show: show)}
end
def render(assigns) do
~H"""
<div class={unless @show, do: "hidden"}>
<%= if @show do %>
<.modal
show
id={@id}
navigate={@show.navigate}
patch={@show.patch}
on_cancel={@show.on_cancel}
on_confirm={@show.on_confirm}
>
<:title><%= @show.title %></:title>
<.live_component module={@show.module} {@show} />
<:cancel>Cancel</:cancel>
<:confirm {@show.confirm_attrs}><%= @show.confirm_text %></:confirm>
</.modal>
<% end %>
</div>
"""
end
end