A project I am working on required adding breadcrumb navigation. If you’re not familiar with the term, it is a list of links usually at the top of the page that represents how you got to the page you are on, like this: Image of breadcrumbs

There were two challenges. First, making this into a reusable component, since it would exist on most pages.

The end result looked like this in the LiveView:

<.breadcrumb links={[
  {"Feature Flags", "/flags"},
  {"Projects", "/flags/projects"},
  {"Environments", "/flags/projects/#{@project_id}/environments"},
  {"Flags", "/flags/projects/#{@project_id}/environments/#{@environment_id}/flags"}
]} />

A tidy list of labels and links for the breadcrumbs. That uses a component defined:

  attr :links, :any, required: true, doc: "two-tuple containing a label and a link"

  def breadcrumb(assigns) do
    ~H"""
    <ul class="mb-4 text-sm">
      <li :for={{label, link} <- @links} class="inline-block pr-1"><a href={link} class="hover:underline pr-1"><%= label %></a></li> 
    </ul>
    """
  end

That gave me a nice inline list of links. But, one thing most breadcrumbs have is a visual separator. In the screenshot, it is single right angle quote.

To add that, I learned that TailwindCSS has great support for psuedo classes. In this case, what I wanted to do was inject content after each link except the final one. The resulting code looks like this:

<li :for={{label, link} <- @links} class="after:content-['›'] inline-block pr-1 last-of-type:after:content-['']">
...