defmodule Phoenix.UI.Components.Breadcrumbs do @moduledoc """ Provides breadcrumbs component. """ import Phoenix.UI.Components.{Heroicon, Link} use Phoenix.UI, :component @default_link_color "slate" @default_separator "chevron-right" @doc """ Renders breadcrumbs component. ## Examples ``` <.breadcrumbs> <:a href={[to: "#"]}>Users <:a href={[to: "#"]}>John Doe <:a>Edit ``` """ @spec breadcrumbs(Socket.assigns()) :: Rendered.t() def breadcrumbs(raw) do assigns = raw |> assign_new(:separator, fn -> @default_separator end) |> build_nav_attrs() |> build_separator_attrs() |> normalize_links() ~H""" """ end ### Nav Attrs ########################## defp build_nav_attrs(assigns) do class = build_class(~w( breadcrumb text-sm font-medium my-6 #{Map.get(assigns, :extend_class)} )) attrs = assigns |> assigns_to_attributes([:extend_class, :a, :size]) |> Keyword.put_new(:class, class) |> Keyword.put_new(:"aria-label", "Breadcrumb") assign(assigns, :nav_attrs, attrs) end ### Separator Attrs ########################## defp build_separator_attrs(assigns) do attrs = %{ name: assigns[:separator], extend_class: "ml-2", color: "slate" } assign(assigns, :separator_attrs, attrs) end ### Normalize Links ########################## defp normalize_links(assigns) do links = assigns |> Map.get(:a, []) |> Enum.reverse() |> Enum.reduce([], fn link, acc -> updated = link |> Map.put_new(:color, @default_link_color) |> apply_aria_current(acc) [updated | acc] end) assign(assigns, :a, links) end defp apply_aria_current(link, []), do: Map.put(link, :"aria-current", "page") defp apply_aria_current(link, _acc), do: link end