Packages
moon
2.72.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/dropdown/bottom_options.ex
defmodule Moon.Design.Dropdown.BottomOptions do
@moduledoc "Options list for the Dropdown component"
# TODO: add panel position options, currently only bottom
use Moon.StatelessComponent
import Moon.Helpers.MakeList
@doc "Value of the selected option(s)"
prop(value, :any, from_context: :value)
@doc "On option click event, in most cases got from context"
prop(on_change, :event, from_context: :on_change)
@doc "Click event, in most cases got from context"
prop(on_close, :event, from_context: :close_me)
@doc "If the optionlist is open, got from context"
prop(is_open, :boolean, from_context: :is_open)
@doc "Size of the options"
prop(size, :string, values!: ~w(sm md lg), default: "md")
@doc "Additional CSS classes for the div"
prop(class, :css_class)
@doc "List of the options. Used when no "
prop(titles, :list, default: [])
prop(option_module, :atom, default: Moon.Design.Dropdown.Option)
@doc "Data-testid attribute for div"
prop(testid, :string)
@doc "Id attribute for div"
prop(id, :string)
@doc """
Experimental: makes BottomSheet behave as Modal on some screen widths,
please reffer to https://tailwindcss.com/docs/screens
"""
prop(as_dropdown_on, :string, values: ~w(sm md lg xl 2xl), from_context: :as_dropdown_on)
slot(option)
slot(default)
def render(assigns) do
~F"""
<div
class={merge([
"fixed inset-x-0 w-full z-[99999] bottom-0 rounded-t-xl shadow-moon-lg box-border bg-goku shadow-moon-lg overflow-y-auto focus:outline-none",
dropdown_classes(@as_dropdown_on),
@class,
hidden: !@is_open,
"flex flex-col absolute z-[99] p-1 my-2 w-full top-full rounded-moon-s-md bottom-auto":
!@as_dropdown_on
])}
{=@id}
data-testid={@testid}
:on-click-away={@on_close}
role="listbox"
>
{#if slot_assigned?(:option)}
{#for {option, index} <- Enum.with_index(make_list(@option))}
<#slot
{option}
context_put={
is_selected: Enum.member?(make_list(@value), option.value || "#{index}"),
size: @size,
on_click: @on_change,
value: index
}
/>
{/for}
{#else}
<.moon
:for={title <- @titles}
module={@option_module}
is_selected={Enum.member?(make_list(@value), title)}
{=@size}
on_click={@on_change}
value={title}
>{title}</.moon>
{/if}
<#slot />
</div>
"""
end
defp dropdown_classes(nil), do: []
defp dropdown_classes(size) do
~w(absolute z-[99] bottom-auto rounded-moon-s-md my-2 shadow-moon-lg box-border top-full)
|> Enum.map(&"#{size}:#{&1}")
end
end