defmodule MusicLibraryWeb.SearchComponents do @moduledoc """ Universal search modal and related components. """ use Phoenix.Component use Gettext, backend: MusicLibraryWeb.Gettext import MusicLibraryWeb.CoreComponents, only: [icon: 1] @doc """ Renders a search trigger button that opens the universal search modal. ## Examples <.search_trigger /> """ attr :class, :string, default: "" attr :rest, :global, include: ~w(phx-click phx-target) def search_trigger(assigns) do ~H""" """ end @doc """ Renders a search result item for records. ## Examples <.search_result_record record={record} selected={false} /> """ attr :record, :map, required: true attr :selected, :boolean, default: false attr :type, :atom, required: true, values: [:collection, :wishlist] attr :rest, :global, include: ~w(phx-click phx-value-id) def search_result_record(assigns) do ~H"""
<.icon name={if @type == :collection, do: "hero-musical-note", else: "hero-heart"} class={"h-5 w-5 #{if @type == :collection, do: "text-green-500", else: "text-red-500"}"} />

{@record.title}

{@record.artists |> Enum.map(& &1.name) |> Enum.join(", ")}

""" end @doc """ Renders a search result item for artists. ## Examples <.search_result_artist artist={artist} selected={false} /> """ attr :artist, :map, required: true attr :selected, :boolean, default: false attr :rest, :global, include: ~w(phx-click phx-value-id) def search_result_artist(assigns) do ~H"""
<.icon name="hero-user" class="h-5 w-5 text-blue-500" />

{@artist.name}

{@artist.disambiguation}

""" end @doc """ Renders a search result group with a title and items. ## Examples <.search_result_group title="Collection" count={3} total_count={10}> <.search_result_record :for={record <- @records} record={record} /> <:actions> """ attr :title, :string, required: true attr :count, :integer, required: true attr :total_count, :integer, default: nil attr :class, :string, default: "" slot :inner_block, required: true slot :actions, doc: "Actions like 'view all' buttons" def search_result_group(assigns) do ~H"""

{@title} ({@count} @count}> of <%= @total_count %> )

{render_slot(@inner_block)}
{render_slot(action)}
""" end @doc """ Renders a view all results button. ## Examples <.view_all_button count={25} target="collection" /> """ attr :count, :integer, required: true attr :target, :string, required: true attr :rest, :global, include: ~w(phx-click phx-value-query) def view_all_button(assigns) do ~H""" """ end @doc """ Renders keyboard shortcut hints. ## Examples <.keyboard_shortcuts /> """ attr :total_results, :integer, default: 0 def keyboard_shortcuts(assigns) do ~H"""
↑↓ Navigate
Select
Esc Close
0} class="text-gray-500 dark:text-gray-400"> {@total_results} results
""" end @doc """ Renders an empty search state. ## Examples <.empty_state /> """ def empty_state(assigns) do ~H"""
<.icon name="hero-magnifying-glass" class="h-12 w-12 text-gray-400 mx-auto mb-4" />

Start typing to search your records and artists

Use Ctrl+K to open this search

""" end @doc """ Renders a no results state. ## Examples <.no_results query="radiohead" /> """ attr :query, :string, required: true def no_results(assigns) do ~H"""
<.icon name="hero-face-frown" class="h-12 w-12 text-gray-400 mx-auto mb-4" />

No results found for "{@query}"

Try a different search term or check your spelling

""" end @doc """ Renders a loading state. ## Examples <.loading_state /> """ def loading_state(assigns) do ~H"""

Searching...

""" end end