Senren UI
Components / Breadcrumb

Breadcrumb

Stable

hierarchical navigation context

Usage example #

Copy this ERB into a Rails view after installing the component. The snippet below is the same code used by the live preview above.

app/views/.../breadcrumb_example.html.erb
<div class="w-full max-w-md">
  <%= render Senren::BreadcrumbComponent.new(items: [
    { label: "Docs", href: "/docs" },
    { label: "Components", href: "/components" },
    { label: "Breadcrumb" }
  ]) %>
</div>

Install this component #

Copy the official component into your app

Use this when you want the Senren-maintained implementation copied into app/components/senren.

Terminal
bin/rails senren:add breadcrumb

Create a custom component with the same conventions

Use this when you need an app-specific static component that follows Senren's ViewComponent structure.

Terminal
bin/rails generate senren:component breadcrumb --no-client

Dependencies are resolved by senren:add: link.

At a glance #

Category Navigation
Class name Senren::BreadcrumbComponent
Stimulus
Variants default
Depends on link
Pairs with page_header

Source #

app/components/senren/breadcrumb_component.html.erb
<% if items.any? %>
  <nav <%= tag.attributes(**root_attrs("text-sm text-[hsl(var(--senren-muted-foreground))]", aria: { label: label })) %>>
    <ol class="flex flex-wrap items-center gap-2">
      <% items.each_with_index do |item, index| %>
        <% current = index == items.length - 1 || item[:href].blank? %>
        <li class="flex items-center gap-2">
          <% if index.positive? %>
            <span aria-hidden="true" class="select-none text-[hsl(var(--senren-muted-foreground)/0.7)]"><%= separator %></span>
          <% end %>
          <% if current %>
            <span aria-current="page" class="font-medium text-[hsl(var(--senren-foreground))]"><%= item[:label] %></span>
          <% else %>
            <%= link_to item[:label], item[:href], class: "transition-colors hover:text-[hsl(var(--senren-foreground))]" %>
          <% end %>
        </li>
      <% end %>
    </ol>
  </nav>
<% else %>
  <nav <%= tag.attributes(**root_attrs("text-sm text-[hsl(var(--senren-muted-foreground))]", aria: { label: label })) %>>
    <%= content %>
  </nav>
<% end %>
app/components/senren/breadcrumb_component.rb
# frozen_string_literal: true

module Senren
  class BreadcrumbComponent < BaseComponent
    VARIANTS = { default: '' }.freeze
    SIZES = { md: '' }.freeze

    def initialize(items: [], label: 'Breadcrumb', separator: '/', class_name: nil, **html)
      super(variant: :default, size: :md, class_name: class_name, **html)
      @items = normalize_items(items)
      @label = label
      @separator = separator
    end

    attr_reader :items, :label, :separator

    private

    def normalize_items(items)
      Array(items).map do |item|
        if item.is_a?(Hash)
          { label: item.fetch(:label) { item.fetch('label') }, href: item[:href] || item['href'] }
        else
          label, href = item
          { label: label, href: href }
        end
      end
    end
  end
end

AI agent rules #

Use for

  • +hierarchical navigation context

Avoid

  • -non-hierarchical pages

Accessibility #

  • aria-label="Breadcrumb"; mark current page with aria-current=page.