defmodule Phoenix.UI.Components.Chip do @moduledoc """ Provides chip component. """ import Phoenix.UI.Components.{Avatar, Heroicon} use Phoenix.UI, :component @default_avatar_size 2 @default_delete_icon_name "x-circle" @default_icon_color "inherit" attr(:avatar, :list) attr(:color, :string, default: "slate", values: Theme.colors()) attr(:delete_icon, :list) attr(:element, :string, default: "div") attr(:extend_class, :string) attr(:icon, :list) attr(:label, :string) attr(:rest, :global) attr(:size, :string, default: "md", values: ["sm", "md"]) attr(:variant, :string, default: "filled", values: ["filled", "outlined"]) @doc """ Renders chip component. ## Examples ``` <.chip label="keto"/> ``` """ @spec chip(Socket.assigns()) :: Rendered.t() def chip(assigns) do assigns = assigns |> assign_class(~w( inline-flex items-center rounded-full text-sm font-semibold transition-all ease-in-out duration-200 #{classes(:clickable, assigns)} #{classes(:size, assigns)} #{classes(:variant, assigns)} )) |> build_avatar_attrs() |> build_icon_attrs() |> build_delete_icon_attrs() ~H""" <.dynamic_tag class={@class} name={@element} {@rest}> <%= if assigns[:avatar] do %> <.avatar {@avatar_attrs} /> <% end %> <%= if !assigns[:avatar] && assigns[:icon] do %> <.heroicon {@icon_attrs} /> <% end %> <%= @label %> <%= if assigns[:delete_icon] do %>
<.heroicon {@delete_icon_attrs} />
<% end %> """ end ### Avatar Attrs ########################## defp build_avatar_attrs(%{avatar: avatar} = assigns) do extend_class = build_class(~w( mr-1 #{Map.get(assigns, :extend_class)} )) attrs = avatar |> assigns_to_attributes() |> Keyword.put(:extend_class, extend_class) |> Keyword.put_new(:size, @default_avatar_size) assign(assigns, :avatar_attrs, attrs) end defp build_avatar_attrs(assigns), do: assigns ### Icon Attrs ########################## defp build_icon_attrs(%{icon: icon} = assigns) do extend_class = build_class(~w( mr-1 #{Map.get(assigns, :extend_class)} )) attrs = icon |> assigns_to_attributes() |> Keyword.put_new(:color, @default_icon_color) |> Keyword.put(:extend_class, extend_class) assign(assigns, :icon_attrs, attrs) end defp build_icon_attrs(assigns), do: assigns ### Delete Icon Attrs ########################## defp build_delete_icon_attrs(%{delete_icon: icon} = assigns) do attrs = icon |> assigns_to_attributes() |> Keyword.put_new(:color, @default_icon_color) |> Keyword.put_new(:name, @default_delete_icon_name) assign(assigns, :delete_icon_attrs, attrs) end defp build_delete_icon_attrs(assigns), do: assigns ### CSS Classes ########################## # Clickable defp classes(:clickable, %{color: color, variant: "filled"} = assigns) do classes = "hover:bg-#{color}-200 dark:hover:bg-#{color}-200 cursor-pointer" case assigns do %{element: el} when el in ["a", "link", "live_patch", "live_redirect"] -> classes %{on_click: _} -> classes _assigns -> nil end end defp classes(:clickable, %{color: color, variant: "outlined"} = assigns) do classes = "hover:bg-#{color}-200/50 dark:hover:bg-#{color}-200/25 cursor-pointer" case assigns do %{element: el} when el in ["a", "link", "live_patch", "live_redirect"] -> classes %{on_click: _} -> classes _assigns -> nil end end # Size defp classes(:size, %{size: "sm", avatar: _}), do: "pl-0 pr-1.5" defp classes(:size, %{size: "sm", icon: _}), do: "py-0.5 pl-1.5 pr-1" defp classes(:size, %{size: "sm"}), do: "py-0.5 px-1.5" defp classes(:size, %{size: "md", avatar: _, delete_icon: _}), do: "pl-0 pr-1" defp classes(:size, %{size: "md", avatar: _}), do: "pl-0 pr-3" defp classes(:size, %{size: "md", icon: _, delete_icon: _}), do: "pl-1 py-1 pr-1" defp classes(:size, %{size: "md", icon: _}), do: "pl-1 py-1 pr-3" defp classes(:size, %{size: "md", delete_icon: _}), do: "py-1 pl-3 pr-1" defp classes(:size, %{size: "md"}), do: "py-1 px-3" # Variant defp classes(:variant, %{color: color, variant: "filled"}) do "bg-#{color}-300 text-#{color}-900 dark:bg-#{color}-400" end defp classes(:variant, %{color: color, variant: "outlined"}) do "border border-#{color}-600 text-#{color}-600 dark:border-#{color}-300 dark:text-#{color}-300" end defp classes(_rule_group, _assigns), do: nil end