Packages
moon
2.79.11
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/components/switch.ex
defmodule Moon.Components.Switch do
@moduledoc false
use Moon.StatelessComponent
alias Moon.Icon
alias Moon.Components.Switch.Caption
alias Phoenix.LiveView.JS
@icons_sizes %{
"small" => "0.75rem",
"medium" => "1rem",
"large" => "1.5rem"
}
prop(id, :string, required: true)
prop(field, :atom, from_context: {Surface.Components.Form.Field, :field})
prop(form, :form, from_context: {Surface.Components.Form, :form})
prop(checked, :boolean, default: false)
prop(icons, :boolean, default: false)
prop(size, :string, values: ["small", "medium", "large"], default: "medium")
prop(action, :string, default: "Toggle Setting")
prop(caption_unchecked, :string)
prop(caption_checked, :string)
prop(icon_name_off, :string, default: "other_moon")
prop(icon_name_on, :string, default: "other_sun")
prop(class, :css_class, default: "")
prop(on_click, :event)
def render(assigns) do
~F"""
<div
{=@id}
class={
"relative inline-flex items-center",
"space-x-1": @size != "large",
"space-x-2": @size == "large",
"#{@class}": @class
}
:on-click={@on_click}
>
<Caption :if={@caption_unchecked} label={@caption_unchecked} size={@size} active={!@checked} />
<Surface.Components.Form.RadioButton
{=@form}
{=@field}
class="hidden"
value="true"
opts={
id: "#{@id}_radio_true",
checked: is_selected(@checked, @form, @field)
}
/>
<Surface.Components.Form.RadioButton
{=@form}
{=@field}
class="hidden"
value="false"
opts={
id: "#{@id}_radio_false",
checked: !is_selected(@checked, @form, @field)
}
/>
<button
type="button"
aria-pressed="false"
class={
"relative inline-flex shrink-0 transition-colors duration-200 ease-in-out border-transparent rounded-full cursor-pointer outline-none focus:outline-none bg-piccolo shadow-md",
"bg-piccolo": is_selected(@checked, @form, @field),
"bg-gohan": !is_selected(@checked, @form, @field),
"border-2 w-7 focus:ring-1 focus:ring-offset-1": @size == "small",
"border-4 w-10 focus:ring-2 focus:ring-offset-1": @size == "medium",
"border-4 w-14 focus:ring-2 focus:ring-offset-2": @size == "large"
}
:on-click={!@on_click &&
JS.dispatch("moon:update-switch",
detail: %{
checked: !is_selected(@checked, @form, @field),
switch_id: @id
},
to: "##{@id}_radio_true"
)}
>
<span class="sr-only">{@action}</span>
<div :if={@icons} class="absolute flex">
<Icon name={@icon_name_off} class="scale-90" font_size={icon_size(@size)} />
<Icon name={@icon_name_on} class="scale-90" font_size={icon_size(@size)} />
</div>
<span
aria-hidden="true"
class={
"inline-block transition duration-200 ease-in-out translate-x-0 bg-gohan rounded-full shadow-md pointer-events-none ring-0 shadow-md",
"w-3 h-3": @size == "small",
"w-4 h-4": @size == "medium",
"w-6 h-6": @size == "large",
"ltr:translate-x-3 rtl:-translate-x-3":
@size == "small" and is_selected(@checked, @form, @field),
"ltr:translate-x-4 rtl:-translate-x-4":
@size == "medium" and is_selected(@checked, @form, @field),
"ltr:translate-x-6 rtl:-translate-x-6":
@size == "large" and is_selected(@checked, @form, @field)
}
/>
</button>
<Caption
:if={@caption_checked}
label={@caption_checked}
size={@size}
active={is_selected(@checked, @form, @field)}
/>
</div>
"""
end
def icon_size(size) do
@icons_sizes[size]
end
def is_true(val) do
Enum.member?([true, "true"], val)
end
def is_selected(checked, form, field) do
is_true(checked) || is_true(Phoenix.HTML.Form.input_value(form, field))
end
end