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/form/dropdown.ex
defmodule Moon.Design.Form.Dropdown do
@moduledoc "Fully styled select component for the forms"
use Moon.StatelessComponent
alias Surface.Components.Form
alias Moon.Design.Dropdown
alias Moon.Design.Form.Checkbox
alias Moon.Design.Form.Radio
import Moon.Helpers.Form
@doc "Name of the field, usually should be taken from context"
prop(field, :atom, from_context: {Form.Field, :field})
@doc "Form info, usually should be taken from context"
prop(form, :form, from_context: {Form, :form})
@doc "... format: [%{key: shown_label, value: option_value, disabled: bool}], diisabled is optional"
prop(options, :list, required: true)
@doc "Selected option(s) value - do not use it inside the form, just for away-from-form components"
prop(value, :any)
@doc "Well, disabled"
prop(disabled, :boolean)
@doc "Common moon size property"
prop(size, :string, values!: ~w(sm md lg), default: "md")
@doc "Additional classes for the <select> tag"
prop(class, :css_class, from_context: :class)
@doc "Some prompt to be shown on empty value"
prop(prompt, :string)
@doc "Id to be given to the select tag"
prop(id, :string)
@doc "Data-testid attribute value"
prop(testid, :string)
@doc "Some additional styling will be set to indicate field is iinvalid"
prop(error, :boolean, from_context: :error)
@doc "If field does support multiselect, `multiple` attribute for select tag in HTML terms"
prop(is_multiple, :boolean)
@doc "Should dropdown be open"
prop(is_open, :boolean)
@doc "Option for custom stylings - use it to show icons or anything else"
slot(default)
@doc "Trigger element for the dropdown, default is Dropdown.Select"
slot(trigger)
@doc "Slot used for rendering single option. option[:key] will be used if not given"
slot(option)
def render(assigns) do
~F"""
<Dropdown id={dropdown_id(assigns)} {=@is_open} {=@class} {=@testid}>
<:trigger :let={is_open: is_open}>
<#slot {@trigger, is_open: is_open}>
<Dropdown.Select
{=@prompt}
{=@size}
{=is_open}
{=@error}
{=@disabled}
value={select_value(assigns) && select_value(assigns)[:key]}
badge={select_badge(assigns)}
>
<#slot {@option, option: select_value(assigns)}>
{(select_value(assigns) && select_value(assigns)[:key]) || @prompt}
</#slot>
</Dropdown.Select>
</#slot>
</:trigger>
<#slot {@default}>
<Dropdown.Options on_change={option_click()}>
<Dropdown.Option :for={option <- @options} {=@size}>
<Checkbox
checked_value={option[:value]}
:if={@is_multiple}
disabled={option[:disabled]}
{=@size}
hidden_input={false}
is_multiple
>
<#slot {@option, option: option}>{option[:key]}</#slot>
</Checkbox>
<Radio.Button value={option[:value]} :if={!@is_multiple} disabled={option[:disabled]} {=@size}>
<Radio.Indicator />
<#slot {@option, option: option}>{option[:key]}</#slot>
</Radio.Button>
</Dropdown.Option>
</Dropdown.Options>
</#slot>
</Dropdown>
"""
end
defp option_click(), do: Phoenix.LiveView.JS.dispatch("moon-empty-event")
end