Packages
moon
2.89.0
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/search.ex
defmodule Moon.Design.Search do
@moduledoc "Textinput with search options. Renders as a Moon.Design.Dropdown. Is designed for usage outside of the forms"
use Moon.StatelessComponent
alias Moon.Design.Dropdown
alias __MODULE__
import Moon.Helpers.Form, only: [input_classes_light: 1]
@doc "... format: [page: Module.Name, key: \"Name\"]"
prop(options, :list, required: true)
@doc "Set disabled/non-disabled"
prop(disabled, :boolean)
@doc "Some prompt to be shown on empty value"
prop(prompt, :string)
@doc "Id of the component"
prop(id, :string, required: true)
@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 "Data-testid attribute value"
prop(testid, :string)
@doc "Some additional styling will be set to indicate field is invalid"
prop(error, :boolean, from_context: :error)
@doc "Should dropdown be open"
prop(is_open, :boolean)
@doc "Filtering value for the options, appears in input"
prop(filter, :string)
@doc "On key up event for the input - use it for filter options"
prop(on_keyup, :event)
@doc "Event that fires when smth is chosen from the dropdown menu"
prop(on_change, :event)
@doc "Additional attributes for the option link"
prop(attrs, :map, default: %{})
@doc "Label to use in the beginning in case of no results"
prop(no_results_label, :string, default: "Search for")
@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)
@doc "When no results are found - this slot will be rendered"
slot(no_result)
def render(assigns) do
~F"""
<div {=@id} class={merge(["w-full", @class])} data-testid={@testid} aria-label="Search">
<Dropdown id={"#{@id}-dropdown"} {=@is_open} hook="Combobox">
<:trigger :let={is_open: is_open}>
<#slot {@trigger, is_open: is_open}>
<Dropdown.Input
placeholder={@prompt}
{=@size}
{=is_open}
{=@error}
{=@disabled}
{=@on_keyup}
value={@filter}
class={
"ps-[2.5rem] bg-goku hover:border-trunks",
input_classes_light(assigns),
"rounded-bl-none rounded-br-none": is_open
}
>
<Search.Icon />
<Search.Button on_click={@on_keyup} />
</Dropdown.Input>
</#slot>
</:trigger>
<#slot {@default}>
<Dropdown.Options
option_module={Dropdown.Link}
{=@on_change}
class="p-2 mt-0 rounded-tl-none rounded-tr-none"
>
<#slot {@option, option: option} :for={option <- @options}>
<Dropdown.Link {=@size} disabled={option[:disabled]} href={option[:page]} {=@attrs}>
{option[:key]}
</Dropdown.Link>
</#slot>
{!-- Use @options == [] to avoid any crash due type input using Enum.empty? --}
<#slot {@no_result, search: @filter, label: @no_results_label, size: @size} :if={@options == []}>
<Search.NoResult label={@no_results_label} search={@filter} {=@size} />
</#slot>
</Dropdown.Options>
</#slot>
</Dropdown>
</div>
"""
end
end