Current section

Files

Jump to
sigma_kit lib components flash.ex
Raw

lib/components/flash.ex

defmodule SigmaKit.Components.Flash do
use Phoenix.LiveComponent
import SigmaKit.Components.Js, only: [show: 1, hide: 1, hide: 2]
import SigmaKit.Components.Flair, only: [indicator: 1]
import SigmaKit.Components.Icons, only: [icon: 1]
alias Phoenix.LiveView.JS
@doc """
## Examples
<.flash kind={:info} flash={@flash} />
<.flash kind={:info} phx-mounted={show("#flash")}>Welcome Back!</.flash>
"""
attr :id, :string, doc: "the optional id of flash container"
attr :flash, :map, default: %{}, doc: "the map of flash messages to display"
attr :kind, :atom, values: [:info, :error], doc: "used for styling and flash lookup"
attr :rest, :global, doc: "the arbitrary HTML attributes to add to the flash container"
attr :details, :list, default: nil
def flash(assigns) when assigns.details == nil do
case Phoenix.Flash.get(assigns.flash, assigns.kind) do
details when is_binary(details) ->
assign(assigns, details: [message: details])
|> flash()
details when is_list(details) ->
assign(assigns, details: details)
|> flash()
nil ->
~H"""
"""
end
end
def flash(assigns) do
assigns = assign_new(assigns, :id, fn -> "flash-#{assigns.kind}" end)
~H"""
<div
id={@id}
phx-hook="FlashHook"
phx-click={JS.push("lv:clear-flash", value: %{key: @kind}) |> hide("##{@id}")}
role="alert"
data-autoclose={Keyword.get(@details, :autoclose, 5000)}
class={[
"fixed bottom-2 right-2 mr-2 overflow-hidden z-50 shadow-lg bg-white border border-zinc-200 opacity-0 min-w-[400px]"
]}
{@rest}
>
<div>
<div
:if={title = Keyword.get(@details, :title)}
class={[
"flex items-center justify-start text-sm font-semibold leading-6 border-b border-zinc-300 py-1 px-2"
]}
>
<.indicator info={@kind == :info} danger={@kind == :error} />
<div>{title}</div>
</div>
<div class={[
"flex gap-4 justify-start p-4 ",
@kind == :info && "fill-blue-400",
@kind == :error && "fill-rose-600"
]}>
<.icon
:if={Keyword.get(@details, :icon)}
name={Keyword.get(@details, :icon)}
class={[
"w-8 h-8",
@kind == :info && "text-blue-400",
@kind == :error && "text-rose-600"
]}
/>
<.flash_icon :if={!Keyword.get(@details, :icon)} kind={@kind} />
<p class="mt-2 text-sm leading-5">
{Keyword.get(@details, :message, "")}
</p>
</div>
<div :if={Keyword.get(@details, :autoclose) != false} class="p-2">
<div class="rounded bg-zinc-600 h-[10px]">
<div class="bg-primary-500 h-[10px] w-[0px] progress"></div>
</div>
</div>
</div>
</div>
"""
end
@doc """
Shows the flash group with standard titles and content.
## Examples
<.flash_group flash={@flash} />
"""
attr :flash, :map, required: true, doc: "the map of flash messages"
attr :id, :string, default: "flash-group", doc: "the optional id of flash container"
def flash_group(assigns) do
~H"""
<div id={@id} class="fixed bottom-2 right-2">
<.flash kind={:info} flash={@flash} />
<.flash kind={:error} flash={@flash} />
</div>
"""
end
attr :kind, :atom
def flash_icon(%{kind: :error} = assigns) do
~H"""
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 640" class="w-8 h-8">
<path d="M382 528C374.9 555.6 349.9 576 320 576C290.1 576 265.1 555.6 258 528L382 528zM352 99.2C425 114 480 178.6 480 256L480 352L560 480L80 480L160 352L160 256C160 178.6 215 114 288 99.2L288 64L352 64L352 99.2zM292 356L292 412L348 412L348 356L292 356zM288 176L300.8 320L339.2 320L352 176L288 176z" />
</svg>
"""
end
def flash_icon(%{kind: :info} = assigns) do
~H"""
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 640" class="w-8 h-8">
<path d="M320 576C461.4 576 576 461.4 576 320C576 178.6 461.4 64 320 64C178.6 64 64 178.6 64 320C64 461.4 178.6 576 320 576zM280 400L304 400L304 336L256 336L256 288L352 288L352 400L384 400L384 448L256 448L256 400L280 400zM352 256L288 256L288 192L352 192L352 256z" />
</svg>
"""
end
end