Packages
moon
2.81.4
2.90.5
retired
2.90.4
2.90.3
2.90.2
2.90.1
2.90.0
2.89.4
2.89.1
2.89.0
2.88.0
2.87.11
2.87.10
2.87.9
2.87.8
2.87.7
2.87.6
2.87.5
2.87.4
2.87.3
2.87.2
2.87.1
2.87.0
2.86.1
2.86.0
2.85.1
2.85.0
2.84.0
2.83.0
2.82.0
2.81.4
2.81.3
2.81.2
2.81.1
2.81.0
2.80.2
2.80.1
2.80.0
2.79.13
2.79.12
2.79.11
2.79.10
2.79.9
2.79.8
2.79.7
2.79.6
2.79.5
2.79.4
2.79.3
2.79.2
2.79.1
2.79.0
2.78.4
2.78.3
2.78.2
2.78.1
2.78.0
2.77.0
2.76.5
2.76.4
2.76.3
2.76.2
2.76.1
2.76.0
2.75.0
2.74.1
2.74.0
2.73.8
2.73.7
2.73.6
2.73.5
2.73.4
2.73.3
2.73.2
2.73.1
2.73.0
2.72.5
2.72.4
2.72.3
2.72.2
2.72.1
2.72.0
2.71.1
2.71.0
2.70.0
2.69.2
2.69.1
2.69.0
2.68.11
2.68.10
Components-based design system written in elixir
Current section
Files
Jump to
Current section
Files
lib/moon/design/snackbar.ex
defmodule Moon.Design.Snackbar do
@moduledoc false
use Moon.StatefulComponent
prop(position, :string,
values: [
"top-left",
"top-center",
"top-right",
"bottom-left",
"bottom-center",
"bottom-right"
],
default: "top-right"
)
slot(trigger)
slot(content)
slot(icon)
slot(close)
prop(is_open, :boolean)
prop(class, :css_class)
prop(outer_class, :css_class)
prop(timeout, :integer, default: 5000)
prop(autoclose, :boolean, default: true)
prop(testid, :string)
def handle_event("set_open", _, socket) do
{:noreply, assign(socket, is_open: true)}
end
def handle_event("set_close", _, socket) do
{:noreply, assign(socket, is_open: false)}
end
@animate_class_map %{
"top-left" => "animate-leftslide",
"bottom-left" => "animate-leftslide",
"top-center" => "animate-topslide",
"bottom-center" => "animate-bottomslide",
"top-right" => "animate-rightslide",
"bottom-right" => "animate-rightslide"
}
defp animate_class(position), do: Map.get(@animate_class_map, position)
@position_class_map %{
"top-left" => "top-4 left-4",
"top-center" => "justify-center top-4 left-4 right-4 md:m-auto",
"top-right" => "justify-end top-4 right-4",
"bottom-left" => "bottom-4 left-4",
"bottom-center" => "justify-center bottom-4 left-4 right-4 m-auto",
"bottom-right" => "justify-end bottom-4 right-4"
}
defp position_class(position), do: Map.get(@position_class_map, position)
def render(assigns) do
~F"""
<div
id={@id}
data-testid={@testid || @id}
data-is_open={@is_open && "true"}
data-autoclose={@autoclose && "true"}
data-timeout={@timeout}
data-animate_class={animate_class(@position)}
data-snackbar="true"
:hook="default"
>
{#if slot_assigned?(:trigger)}
<div id={@id <> "-trigger"} data-testid={"#{@testid || @id}-trigger"} :on-click="set_open">
<#slot {@trigger} />
</div>
{/if}
<div
id={@id <> "-content"}
class={merge([
"z-[9999999] flex fixed w-[calc(100%-32px)] md:w-fit transition hidden",
position_class(@position),
@outer_class
])}
data-testid={"#{@testid || @id}-content"}
aria-hidden={(@is_open && "true") || "false"}
>
<div class={merge([
"flex w-fit max-w-xs items-center gap-4 p-4 bg-goku shadow-moon-lg rounded-moon-s-sm",
@class
])}>
<#slot {@icon} />
<#slot {@content} />
{#if slot_assigned?(:close)}
<div :on-click="set_close">
<#slot {@close} />
</div>
{/if}
</div>
</div>
</div>
"""
end
end