Menu

Breadcrumb

render Components::Breadcrumb.new do |breadcrumb|
  breadcrumb.list do
    breadcrumb.link(href: "") { "Home" }
    breadcrumb.separator
    breadcrumb.link(href: "") { "Components" }
    breadcrumb.separator
    breadcrumb.item { "Breadcrumb" }
  end
end

Installation

Add the component to your project

CLI

Run the following command in your terminal

bundle exec essence add breadcrumb
Manually

Add the following code and libraries into your project

components/breadcrumb.rb
# frozen_string_literal: true

class Components::Breadcrumb < Components::Essence
  attr_reader :size, :items

  def initialize(size: :md, items: [], **attributes)
    @size = size
    @items = items
    super(**attributes)
  end

  def view_template(&)
    return nav(**attributes, &) if items.empty?
    nav(**attributes) { generate_from_items }
  end

  def list(**, &) = ol(**m(**), &)
  def link(**, &) = li { a(**m(**), &) }
  def separator(**) = span(**m(**)) { block_given? ? yield : "/" }

  def item(current: false, **mattributes, &)
    modifiers = { "aria-current": !!current ? "page" : nil, current: }
    li(**m(modifiers:, **mattributes), &)
  end

  private

  def generate_from_items
    return if items.empty?
    list do
      items.each_with_index do |item, index|
        if !item[:href].nil?
          link(href: item[:href], current: !!item[:current]) { item[:text] }
        else
          item(current: !!item[:current]) { item[:text] }
        end
        separator if index < items.size - 1
      end
    end
  end

  def component_classes
    {
      _: {
        _: "font-medium",
        size: {
          none: "",
          sm: "text-xs",
          md: "text-sm",
          lg: "text-base"
        }
      },
      list: {
        _: "flex items-center gap-2",
        size: {
          none: "",
          sm: "text-xs",
          md: "text-sm",
          lg: "text-base"
        }
      },
      item: {
        _: "text-gray-950/60",
        current: {
          true => "text-gray-950",
          false => ""
        }
      },
      link: {
        _: "text-gray-950/60 hover:text-gray-950"
      },
      separator: {
        _: "text-gray-950/20"
      }
    }.freeze
  end

  def component_attributes
    {
      _: { "aria-label": "breadcrumb" },
      separator: { "aria-hidden": "true" }
    }.freeze
  end
end