Skip to content
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
2fdaf97
Change page header component and make the breadcumbs optional, show c…
bsatarnejad Oct 24, 2025
7c51730
Create thin-terms-shout.md
bsatarnejad Oct 24, 2025
4e4febc
Generating component snapshots
bsatarnejad Oct 24, 2025
ab5ba5e
update page header test
bsatarnejad Oct 24, 2025
c81040e
Generating component snapshots
bsatarnejad Oct 24, 2025
1d11e23
add a test for rendering page header without breadcrumbs
bsatarnejad Oct 24, 2025
1b87f77
add a test to check if the context bar exist only for mobile actions
bsatarnejad Oct 24, 2025
c6fad7f
when there is no breadcrumbs, show actions in the title bar
bsatarnejad Oct 24, 2025
4134e0f
simplify rendering mobile actions
bsatarnejad Oct 24, 2025
76a9f09
show contextbar in mobile mode
bsatarnejad Oct 27, 2025
8dcc937
make the breadcrumbs required
bsatarnejad Oct 27, 2025
33b6cf8
move breadcrumbs previews close to each other
bsatarnejad Oct 27, 2025
13a6aa5
change test
bsatarnejad Oct 27, 2025
b6e95c2
move show_state out of private section
bsatarnejad Oct 27, 2025
f400cf5
add class for no breadcrumbs state before rendering the component
bsatarnejad Oct 28, 2025
e454ec4
add class for no breadcrumbs state while rendering the component
bsatarnejad Oct 28, 2025
940061a
add class for no breadcrumbs state in rendering breadcrumbs
bsatarnejad Oct 29, 2025
d519a8b
handle showing and hiding context bar in page ehader
bsatarnejad Oct 29, 2025
37d32c3
check for added class in the test
bsatarnejad Oct 29, 2025
382be26
change the patch to minor in the changeset
bsatarnejad Oct 29, 2025
9d76d51
remove default nil value for breadcrumbs
bsatarnejad Oct 30, 2025
1641c66
fix style lint errors
bsatarnejad Oct 30, 2025
a8ddab6
add comment to the styles
bsatarnejad Nov 4, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/thin-terms-shout.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@openproject/primer-view-components": patch
Comment thread
bsatarnejad marked this conversation as resolved.
Outdated
---

[67724] Make breadcrumbs optional in page header component
29 changes: 13 additions & 16 deletions app/components/primer/open_project/page_header.html.erb
Original file line number Diff line number Diff line change
@@ -1,20 +1,12 @@
<%= render Primer::BaseComponent.new(**@system_arguments) do %>
<% if @parent_link || breadcrumbs || actions.any? %>
<div class="PageHeader-contextBar">
<%= @parent_link %>
<%= breadcrumbs %>
<% if @mobile_segmented_control %>
<%= render(@mobile_segmented_control, &@mobile_segmented_control_block) %>
<% end %>
<% if render_mobile_menu? %>
<%= render(@mobile_action_menu) do |menu| %>
<% menu.with_show_button(icon: :"kebab-horizontal", size: :small, "aria-label": @mobile_menu_label) %>
<% @desktop_menu_block.call(menu) unless @desktop_menu_block.nil? %>
<% end %>
<% elsif actions.length == 1 && @mobile_action.present? %>
<%= render(@mobile_action) { |el| @mobile_action_block.call(el) unless @mobile_action_block.nil?} %>
<% end %>
</div>
<% if breadcrumbs %>
<% if @parent_link || actions.any? %>
Comment thread
bsatarnejad marked this conversation as resolved.
Outdated
<div class="PageHeader-contextBar">
<%= @parent_link %>
<%= breadcrumbs %>
<%= render_mobile_actions %>
</div>
<% end %>
<% end %>

<div class="PageHeader-titleBar">
Expand All @@ -25,6 +17,11 @@
<% actions.each do |action| %>
<%= action %>
<% end %>

<%# If there are no breadcrumbs, render mobile actions in the title bar instead %>
<% unless breadcrumbs %>
<%= render_mobile_actions %>
<% end %>
</div>
<% end %>
</div>
Expand Down
25 changes: 23 additions & 2 deletions app/components/primer/open_project/page_header.rb
Original file line number Diff line number Diff line change
Expand Up @@ -261,10 +261,10 @@ def initialize(mobile_menu_label: I18n.t("label_more"), state: STATE_DEFAULT, **
end

def render?
raise ArgumentError, "PageHeader needs a title and a breadcrumb. Please use the `with_title` and `with_breadcrumbs` slot" unless breadcrumbs? || Rails.env.production?
Comment thread
bsatarnejad marked this conversation as resolved.
raise ArgumentError, "PageHeader needs a title. Please use the `with_title` slot" unless title? || Rails.env.production?
raise ArgumentError, "PageHeader allows only a maximum of 5 actions" if actions.count > 5

title? && breadcrumbs?
title?
end

def render_mobile_menu?
Expand All @@ -275,6 +275,27 @@ def show_state?
@state == STATE_DEFAULT
end

def render_mobile_actions
safe_join([
(render(@mobile_segmented_control, &@mobile_segmented_control_block) if @mobile_segmented_control),
Comment thread
bsatarnejad marked this conversation as resolved.
Outdated
(render_mobile_action_menu if render_mobile_menu?),
(render_single_mobile_action if actions.one? && @mobile_action.present?)
].compact)
Comment thread
bsatarnejad marked this conversation as resolved.
Outdated
end

private

def render_mobile_action_menu
render(@mobile_action_menu) do |menu|
menu.with_show_button(icon: :"kebab-horizontal", size: :small, "aria-label": @mobile_menu_label)
@desktop_menu_block&.call(menu)
end
end

def render_single_mobile_action
render(@mobile_action) { |el| @mobile_action_block&.call(el) }
end

private

def set_action_arguments(system_arguments, scheme: nil)
Expand Down
13 changes: 13 additions & 0 deletions previews/primer/open_project/page_header_preview.rb
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,19 @@ def skip_breadcrumb_item
def description
render_with_template(template: "primer/open_project/page_header_preview/description")
end

# @label Without breadcrumbs
# A PageHeader example that renders without breadcrumbs.
Comment thread
bsatarnejad marked this conversation as resolved.
Outdated
def without_breadcrumbs
Comment thread
bsatarnejad marked this conversation as resolved.
Outdated
render(Primer::OpenProject::PageHeader.new) do |header|
header.with_title { "Hello" }
header.with_description { "This PageHeader does not have any breadcrumbs." }
header.with_action_button(mobile_icon: "star", mobile_label: "Star") do |button|
button.with_leading_visual_icon(icon: "star")
"Star"
end
end
end
end
end
end
78 changes: 66 additions & 12 deletions test/components/primer/open_project/page_header_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,7 @@ def test_raises_if_no_title_provided
render_inline(Primer::OpenProject::PageHeader.new)
end

assert_equal("PageHeader needs a title and a breadcrumb. Please use the `with_title` and `with_breadcrumbs` slot", err.message)
end

def test_raises_if_no_breadcrumb_provided
err = assert_raises ArgumentError do
render_inline(Primer::OpenProject::PageHeader.new) do |header|
header.with_title { "Hello" }
end

end

assert_equal("PageHeader needs a title and a breadcrumb. Please use the `with_title` and `with_breadcrumbs` slot", err.message)
assert_equal("PageHeader needs a title. Please use the `with_title` slot", err.message)
end

def test_renders_title
Expand Down Expand Up @@ -290,6 +279,71 @@ def test_skips_a_breadcrumb_item_for_mobile
assert_selector("nav[aria-label='Breadcrumb'].PageHeader-breadcrumbs .breadcrumb-item.text-bold a[href='#']")
end

def test_renders_without_breadcrumbs
render_inline(Primer::OpenProject::PageHeader.new) do |header|
header.with_title { "Hello" }
end

# Title is rendered
assert_text("Hello")
assert_selector(".PageHeader-title")

# Breadcrumbs and parent link are not rendered
assert_no_selector(".PageHeader-breadcrumbs")
Comment thread
bsatarnejad marked this conversation as resolved.
assert_no_selector(".PageHeader-parentLink")

# Context bar should not be rendered when no breadcrumbs or parent link exist
assert_no_selector(".PageHeader-contextBar")
end

def test_renders_actions_without_breadcrumbs
render_inline(Primer::OpenProject::PageHeader.new(show_state: true)) do |header|
header.with_title { "Hello" }
header.with_action_button(mobile_icon: "pencil", mobile_label: "Edit") { "Edit" }
header.with_action_icon_button(icon: "trash", mobile_icon: "trash", label: "Delete") { "Delete" }
header.with_action_link(mobile_icon: "link", mobile_label: "Go to", href: "https://openproject.org") { "Go to OpenProject" }
end

assert_text("Hello")
assert_selector(".PageHeader-title")
assert_selector(".PageHeader-actions")
assert_text("Edit")
assert_text("Delete")
assert_text("Go to OpenProject")
assert_no_selector(".PageHeader-contextBar")
assert_no_selector(".PageHeader-breadcrumbs")
assert_no_selector(".PageHeader-parentLink")

# At least one mobile action button or menu should exist
assert_selector(".PageHeader-actions .Button, .PageHeader-actions action-menu", minimum: 1)
end

def test_renders_with_mobile_segmented_control
render_inline(Primer::OpenProject::PageHeader.new(show_state: true)) do |header|
header.with_title { "Title" }
header.with_action_segmented_control(
"aria-label": "Segmented control",
mobile_system_arguments: { hide_labels: true }
) do |control|
control.with_item(label: "Preview", icon: :eye, selected: true)
control.with_item(label: "Raw", icon: :"file-code")
end
end

assert_selector(".PageHeader-action")
assert_selector(".PageHeader-action.SegmentedControl")
Comment thread
bsatarnejad marked this conversation as resolved.
Outdated
end

def test_renders_single_action_with_mobile_action
render_inline(Primer::OpenProject::PageHeader.new(show_state: true)) do |header|
header.with_title { "Single Action Test" }
header.with_action_button(mobile_icon: "plus", mobile_label: "Add") { "Add" }
end

assert_text("Add")
Comment thread
bsatarnejad marked this conversation as resolved.
Outdated
end


private

def breadcrumb_elements
Expand Down
Loading