Skip to content

Commit 81712dd

Browse files
committed
Add Breadcrumb components
Extracted from Uchi's component library (www.uchiadmin.com).
1 parent 9bc8fcb commit 81712dd

File tree

9 files changed

+445
-0
lines changed

9 files changed

+445
-0
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ This project adheres to [Semantic Versioning](http://semver.org/).
77

88
### Added
99

10+
* Breadcrumb component, including Flowbite::BreadcrumbItem with Flowbite::BreadcrumbItem::First and Flowbite::BreadcrumbItem::Current variants.
1011
* DateTime input field components.
1112
* Toast component.
1213

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
# frozen_string_literal: true
2+
3+
module Flowbite
4+
# Renders a breadcrumb navigation component.
5+
#
6+
# See https://flowbite.com/docs/components/breadcrumb/
7+
#
8+
# @example Basic usage with BreadcrumbItem components
9+
# <%= render Flowbite::Breadcrumb.new do |breadcrumb| %>
10+
# <% breadcrumb.with_item do %>
11+
# <%= render Flowbite::BreadcrumbItem::First.new(href: "/") { "Home" } %>
12+
# <% end %>
13+
# <% breadcrumb.with_item do %>
14+
# <%= render Flowbite::BreadcrumbItem.new(href: "/projects") { "Projects" } %>
15+
# <% end %>
16+
# <% breadcrumb.with_item do %>
17+
# <%= render Flowbite::BreadcrumbItem::Current.new { "Current Page" } %>
18+
# <% end %>
19+
# <% end %>
20+
class Breadcrumb < ViewComponent::Base
21+
renders_many :items
22+
23+
def call
24+
content_tag(:nav, class: "flex", "aria-label": "Breadcrumb") do
25+
content_tag(:ol, class: "inline-flex items-center space-x-1 md:space-x-2 rtl:space-x-reverse") do
26+
items.each do |item|
27+
concat(item)
28+
end
29+
end
30+
end
31+
end
32+
end
33+
end
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# frozen_string_literal: true
2+
3+
module Flowbite
4+
# Renders a breadcrumb home icon.
5+
#
6+
# This is typically used as a prefix icon in the first breadcrumb item,
7+
# but can be used standalone if needed.
8+
#
9+
# @example Standalone usage
10+
# <%= render Flowbite::BreadcrumbHome.new %>
11+
class BreadcrumbHome < ViewComponent::Base
12+
def call
13+
tag.svg(
14+
class: "w-3 h-3 me-2.5",
15+
"aria-hidden": "true",
16+
xmlns: "http://www.w3.org/2000/svg",
17+
fill: "currentColor",
18+
viewBox: "0 0 20 20"
19+
) do
20+
tag.path(
21+
d: "m19.707 9.293-2-2-7-7a1 1 0 0 0-1.414 0l-7 7-2 2a1 1 0 0 0 1.414 1.414L2 10.414V18a2 2 0 0 0 2 2h3a1 1 0 0 0 1-1v-4a1 1 0 0 1 1-1h2a1 1 0 0 1 1 1v4a1 1 0 0 0 1 1h3a2 2 0 0 0 2-2v-7.586l.293.293a1 1 0 0 0 1.414-1.414Z"
22+
)
23+
end
24+
end
25+
end
26+
end
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
# frozen_string_literal: true
2+
3+
module Flowbite
4+
# Base class for rendering a breadcrumb item (middle items in the breadcrumb trail).
5+
#
6+
# @param href [String] The URL for the breadcrumb link.
7+
# @param options [Hash] Additional HTML attributes to pass to the link element.
8+
#
9+
# @example Middle item
10+
# <%= render Flowbite::BreadcrumbItem.new(href: "/projects") { "Projects" } %>
11+
class BreadcrumbItem < ViewComponent::Base
12+
attr_reader :href, :options
13+
14+
def initialize(href:, **options)
15+
super()
16+
@href = href
17+
@options = options
18+
end
19+
20+
def call
21+
content_tag(:li, item_options) do
22+
content_tag(:div, class: "flex items-center") do
23+
concat(render(prefix_icon)) if prefix_icon
24+
concat(render_link)
25+
end
26+
end
27+
end
28+
29+
protected
30+
31+
def item_options
32+
{}
33+
end
34+
35+
def prefix_icon
36+
Flowbite::BreadcrumbSeparator.new
37+
end
38+
39+
def render_link
40+
link_options = {class: link_classes}.merge(options)
41+
content_tag(:a, content, href: href, **link_options)
42+
end
43+
44+
def link_classes
45+
["ms-1", "text-sm", "font-medium", "text-body", "hover:text-fg-brand"]
46+
end
47+
end
48+
end
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
# frozen_string_literal: true
2+
3+
module Flowbite
4+
class BreadcrumbItem
5+
# Renders the current page breadcrumb item.
6+
# Current items are rendered as non-interactive spans with different styling.
7+
#
8+
# @param options [Hash] Additional HTML attributes to pass to the span element.
9+
#
10+
# @example Current page item
11+
# <%= render Flowbite::BreadcrumbItem::Current.new { "Current Page" } %>
12+
class Current < BreadcrumbItem
13+
def initialize(**options)
14+
super(href: nil, **options)
15+
end
16+
17+
protected
18+
19+
def item_options
20+
{"aria-current": "page"}
21+
end
22+
23+
def render_link
24+
link_options = {class: link_classes}.merge(options)
25+
content_tag(:span, content, **link_options)
26+
end
27+
28+
def link_classes
29+
["ms-1", "text-sm", "font-medium", "text-body-subtle"]
30+
end
31+
end
32+
end
33+
end
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
# frozen_string_literal: true
2+
3+
module Flowbite
4+
class BreadcrumbItem
5+
# Renders the first breadcrumb item (typically home).
6+
# First items don't show a separator icon.
7+
#
8+
# @param href [String] The URL for the breadcrumb link.
9+
# @param options [Hash] Additional HTML attributes to pass to the link element.
10+
#
11+
# @example First item
12+
# <%= render Flowbite::BreadcrumbItem::First.new(href: "/") { "Home" } %>
13+
class First < BreadcrumbItem
14+
protected
15+
16+
def item_options
17+
{class: "inline-flex items-center"}
18+
end
19+
20+
def link_classes
21+
["text-sm", "font-medium", "inline-flex", "items-center", "text-body", "hover:text-fg-brand"]
22+
end
23+
24+
def prefix_icon
25+
nil
26+
end
27+
28+
def render_link
29+
icon = render(Flowbite::BreadcrumbHome.new)
30+
link_options = {class: link_classes}.merge(options)
31+
content_tag(:a, safe_join([icon, content]), href: href, **link_options)
32+
end
33+
end
34+
end
35+
end
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# frozen_string_literal: true
2+
3+
module Flowbite
4+
# Renders a breadcrumb separator icon.
5+
#
6+
# This is automatically used by BreadcrumbItem components, but can be
7+
# used standalone if needed.
8+
#
9+
# @example Standalone usage
10+
# <%= render Flowbite::BreadcrumbSeparator.new %>
11+
class BreadcrumbSeparator < ViewComponent::Base
12+
def call
13+
tag.svg(
14+
class: "w-3.5 h-3.5 rtl:rotate-180 text-body",
15+
"aria-hidden": "true",
16+
xmlns: "http://www.w3.org/2000/svg",
17+
fill: "none",
18+
height: 24,
19+
viewBox: "0 0 24 24",
20+
width: 24
21+
) do
22+
tag.path(
23+
stroke: "currentColor",
24+
"stroke-linecap": "round",
25+
"stroke-linejoin": "round",
26+
"stroke-width": "2",
27+
d: "m9 5 7 7-7 7"
28+
)
29+
end
30+
end
31+
end
32+
end
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# frozen_string_literal: true
2+
3+
class BreadcrumbPreview < Lookbook::Preview
4+
# Use breadcrumb navigation to show the current page location and allow users
5+
# to navigate back through the hierarchy.
6+
def default
7+
render(Flowbite::Breadcrumb.new) do |breadcrumb|
8+
breadcrumb.with_item do
9+
render_to_string(Flowbite::BreadcrumbItem::First.new(href: "/").with_content("Home"))
10+
end
11+
breadcrumb.with_item do
12+
render_to_string(Flowbite::BreadcrumbItem.new(href: "/projects").with_content("Projects"))
13+
end
14+
breadcrumb.with_item do
15+
render_to_string(Flowbite::BreadcrumbItem::Current.new.with_content("Current Page"))
16+
end
17+
end
18+
end
19+
20+
private
21+
22+
def render_to_string(component)
23+
ApplicationController.render(component, layout: false)
24+
end
25+
end

0 commit comments

Comments
 (0)