lib/moon/design/dropdown/select.ex

defmodule Moon.Design.Dropdown.Select do
  @moduledoc "Element that triggers Dropdown component, renders as a button"

  use Moon.StatelessComponent, slot: "trigger"

  alias Moon.Icon
  alias Moon.Design.Dropdown.Badge

  @doc "Data-testid attribute for html tag"
  prop(testid, :string)
  @doc "Id attribute for html tag"
  prop(id, :string)
  @doc "Additional CSS classes for the html tag"
  prop(class, :css_class)

  @doc "Text to be shown when no value given"
  prop(prompt, :string, default: "...")
  @doc "Value to be shown"
  prop(value, :string)
  @doc "Badge to show selected items count or smth else"
  prop(badge, :integer)

  @doc "Some additional styling will be set to indicate field is iinvalid"
  prop(error, :boolean, from_context: :error)
  @doc "If the open indicator is active or not"
  prop(is_open, :boolean, from_context: :is_open)
  @doc "Site of the select"
  prop(size, :string, values!: ~w(sm md lg), from_context: :size)
  @doc "If the item should be marked as disabled"
  prop(disabled, :boolean, from_context: :disabled)
  @doc "Event that fired when trigger is clicked"
  prop(on_click, :event, from_context: :on_trigger)
  @doc "Content of the button"
  slot(default)

  def render(assigns) do
    ~F"""
    <button
      {=@id}
      data-testid={@testid}
      type="button"
      :on-click={!@disabled && @on_click}
      {=@error}
      {=@disabled}
      class={merge([
        "flex items-center w-full bg-goku border-beerus",
        "shadow-input hover:shadow-input-hov transition-shadow duration-200",
        "focus:shadow-input-focus focus:outline-none py-0 pe-4 m-0",
        "moon-error:shadow-input-err moon-error:hover:shadow-input-err moon-error:focus:shadow-input-err",
        [
          "h-8 leading-8 rounded-moon-i-xs text-moon-14 ps-2": @size == "sm",
          "h-10 leading-10 rounded-moon-i-sm text-moon-16 ps-2 ": !(@size in ~w(sm lg)),
          "h-12 leading-[3rem] rounded-moon-i-sm text-moon-16 ps-3": @size == "lg",
          "opacity-60 outline-0 border-none cursor-not-allowed hover:shadow-input focus:shadow-input":
            @disabled
        ],
        get_config(:default_class),
        @class
      ])}
    >
      <Badge :if={@badge && @badge > 0} {=@size} count={@badge} />
      <span class={merge([
        "overflow-hidden whitespace-nowrap text-trunks ps-2",
        "text-bulma": !!@value
      ])}>
        <#slot>{@value || @prompt}</#slot>
      </span>
      <Icon
        name="controls_chevron_down"
        class={"text-trunks flex-shrink-0 transition-transform ltr:ml-auto rtl:mr-auto", "rotate-180": @is_open}
      />
    </button>
    """
  end
end