Skip to content

Commit 5ba81bb

Browse files
authored
Merge pull request #49 from opf/51013-add-parent-link-actions-and-responsiveness
feat[#51013]: Extend page header with parent link, context bar actions and responsiveness
2 parents 61f4e48 + 841f449 commit 5ba81bb

8 files changed

Lines changed: 198 additions & 11 deletions

File tree

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@openproject/primer-view-components': minor
3+
---
4+
5+
Extend page header with parent link, context bar actions and responsiveness
Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,17 @@
11
<%= render Primer::BaseComponent.new(**@system_arguments) do %>
2-
<%= breadcrumbs %>
2+
<% if parent_link || breadcrumbs || context_bar_actions %>
3+
<div class="PageHeader-contextBar">
4+
<%= parent_link %>
5+
<%= breadcrumbs %>
6+
<%= context_bar_actions %>
7+
</div>
8+
<% end %>
9+
310
<div class="PageHeader-titleBar">
411
<%= back_button %>
512
<%= title %>
613
<%= actions %>
714
</div>
15+
816
<%= description %>
917
<% end %>

app/components/primer/open_project/page_header.pcss

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,13 @@
1212
}
1313
}
1414

15+
.PageHeader-contextBar {
16+
display: flex;
17+
flex-flow: row;
18+
justify-content: flex-end;
19+
align-items: center;
20+
}
21+
1522
.PageHeader-titleBar {
1623
display: flex;
1724
flex-flow: row;
@@ -38,8 +45,9 @@
3845

3946
/* Add 1 or 2 buttons to the right of the heading */
4047
.PageHeader-actions {
41-
margin: var(--base-size-4) 0 var(--base-size-4) var(--base-size-4);
48+
margin: 0 0 0 var(--base-size-4);
4249
justify-content: flex-end;
50+
display: flex;
4351

4452
& + .PageHeader-description {
4553
margin-top: var(--base-size-4);
@@ -50,9 +58,19 @@
5058
display: block;
5159
width: 100%;
5260
margin-bottom: var(--base-size-8);
61+
padding-bottom: var(--base-size-4);
5362
}
5463

5564
.PageHeader-backButton {
5665
margin-top: 2px; /* to center align with label */
5766
margin-right: var(--base-size-4);
5867
}
68+
69+
.PageHeader-parentLink {
70+
flex: 1 1 auto;
71+
margin-bottom: var(--base-size-4);
72+
}
73+
74+
.PageHeader-contextBarActions {
75+
margin: 0 0 0 var(--base-size-4);
76+
}

app/components/primer/open_project/page_header.rb

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,11 @@ class PageHeader < Primer::Component
2727
"triangle-left"
2828
].freeze
2929

30+
DEFAULT_BACK_BUTTON_DISPLAY = [:none, :flex].freeze
31+
DEFAULT_BREADCRUMBS_DISPLAY = [:none, :flex].freeze
32+
DEFAULT_PARENT_LINK_DISPLAY = [:block, :none].freeze
33+
DEFAULT_CONTEXT_BAR_ACTIONS_DISPLAY = [:block, :none].freeze
34+
3035
status :open_project
3136

3237
# The title of the page header
@@ -64,7 +69,21 @@ class PageHeader < Primer::Component
6469
Primer::BaseComponent.new(**system_arguments)
6570
}
6671

72+
# Context Bar Actions
73+
# By default shown on narrow screens. Can be overridden with system_argument: display
74+
#
75+
# @param system_arguments [Hash] <%= link_to_system_arguments_docs %>
76+
renders_one :context_bar_actions, lambda { |**system_arguments|
77+
deny_tag_argument(**system_arguments)
78+
system_arguments[:tag] = :div
79+
system_arguments[:classes] = class_names(system_arguments[:classes], "PageHeader-contextBarActions")
80+
system_arguments[:display] ||= DEFAULT_CONTEXT_BAR_ACTIONS_DISPLAY
81+
82+
Primer::BaseComponent.new(**system_arguments)
83+
}
84+
6785
# Optional back button prepend the title
86+
# By default shown on wider screens. Can be overridden with system_argument: display
6887
#
6988
# @param size [Symbol] <%= one_of(Primer::OpenProject::PageHeader::BACK_BUTTON_SIZE_OPTIONS) %>
7089
# @param icon [String] <%= one_of(Primer::OpenProject::PageHeader::BACK_BUTTON_ICON_OPTIONS) %>
@@ -80,16 +99,35 @@ class PageHeader < Primer::Component
8099
system_arguments[:size] = fetch_or_fallback(BACK_BUTTON_SIZE_OPTIONS, size, DEFAULT_BACK_BUTTON_SIZE)
81100
system_arguments[:icon] = fetch_or_fallback(BACK_BUTTON_ICON_OPTIONS, icon, DEFAULT_BACK_BUTTON_ICON)
82101
system_arguments[:classes] = class_names(system_arguments[:classes], "PageHeader-backButton")
102+
system_arguments[:display] ||= DEFAULT_BACK_BUTTON_DISPLAY
83103

84104
Primer::Beta::IconButton.new(**system_arguments)
85105
}
86106

107+
# Optional parent link in the context area
108+
# By default shown on narrow screens. Can be overridden with system_argument: display
109+
#
110+
# @param system_arguments [Hash] <%= link_to_system_arguments_docs %>
111+
renders_one :parent_link, lambda { |icon: DEFAULT_BACK_BUTTON_ICON, **system_arguments, &block|
112+
deny_tag_argument(**system_arguments)
113+
system_arguments[:icon] = fetch_or_fallback(BACK_BUTTON_ICON_OPTIONS, icon, DEFAULT_BACK_BUTTON_ICON)
114+
system_arguments[:classes] = class_names(system_arguments[:classes], "PageHeader-parentLink")
115+
system_arguments[:display] ||= DEFAULT_PARENT_LINK_DISPLAY
116+
117+
render(Primer::Beta::Link.new(scheme: :primary, muted: true, **system_arguments)) do
118+
render(Primer::Beta::Octicon.new(icon: "arrow-left", "aria-label": "aria_label", mr: 2)) + content_tag(:span, &block)
119+
end
120+
}
121+
87122
# Optional breadcrumbs above the title row
123+
# By default shown on wider screens. Can be overridden with system_argument: display
88124
#
89125
# @param items [Array<String, Hash>] Items is an array of strings, hash {href, text} or an anchor tag string
90126
# @param system_arguments [Hash] <%= link_to_system_arguments_docs %>
91127
renders_one :breadcrumbs, lambda { |items, **system_arguments|
92128
system_arguments[:classes] = class_names(system_arguments[:classes], "PageHeader-breadcrumbs")
129+
system_arguments[:display] ||= DEFAULT_BREADCRUMBS_DISPLAY
130+
93131
render(Primer::Beta::Breadcrumbs.new(**system_arguments)) do |breadcrumbs|
94132
items.each do |item|
95133
item = anchor_string_to_object(item) if anchor_tag_string?(item)

previews/primer/open_project/page_header_preview.rb

Lines changed: 48 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -21,22 +21,32 @@ def default
2121
# @param with_back_button [Boolean]
2222
# @param back_button_size [Symbol] select [small, medium, large]
2323
# @param with_breadcrumbs [Boolean]
24+
# @param with_actions [Boolean]
25+
# @param with_context_bar_actions [Boolean]
26+
# @param with_parent_link [Boolean]
2427
def playground(
2528
variant: :medium,
2629
title: "Hello",
2730
description: "Last updated 5 minutes ago by XYZ.",
2831
with_back_button: false,
2932
back_button_size: :medium,
30-
with_breadcrumbs: false
33+
with_breadcrumbs: false,
34+
with_actions: false,
35+
with_context_bar_actions: false,
36+
with_parent_link: false
3137
)
3238
breadcrumb_items = [{ href: "/foo", text: "Foo" }, { href: "/bar", text: "Bar" }, "Baz"]
3339

34-
render(Primer::OpenProject::PageHeader.new) do |header|
35-
header.with_title(variant: variant) { title }
36-
header.with_description { description }
37-
header.with_back_button(href: "#", size: back_button_size, 'aria-label': "Back") if with_back_button
38-
header.with_breadcrumbs(breadcrumb_items) if with_breadcrumbs
39-
end
40+
render_with_template(locals: { variant: variant,
41+
title: title,
42+
description: description,
43+
with_back_button: with_back_button,
44+
back_button_size: back_button_size,
45+
with_breadcrumbs: with_breadcrumbs,
46+
with_parent_link: with_parent_link,
47+
with_actions: with_actions,
48+
with_context_bar_actions: with_context_bar_actions,
49+
breadcrumb_items: breadcrumb_items })
4050
end
4151

4252
# @label Large
@@ -52,7 +62,11 @@ def actions
5262
render_with_template(locals: {})
5363
end
5464

55-
# @label With back button
65+
# @label With back button (on wide)
66+
# **Back button** is only shown on **wider than narrow screens** by default.
67+
# If you want to override that behaviour please use the system_argument: **display**
68+
# e.g. **component.with\_breadcrumbs(display: [:block, :block])**
69+
#
5670
# @param href [String] text
5771
# @param size [Symbol] select [small, medium, large]
5872
# @param icon [String] select ["arrow-left", "chevron-left", "triangle-left"]
@@ -63,7 +77,11 @@ def back_button(href: "#", size: :medium, icon: "arrow-left")
6377
end
6478
end
6579

66-
# @label With breadcrumbs
80+
# @label With breadcrumbs (on wide)
81+
# **Breadcrumbs** are only shown on **wider than narrow screens** by default.
82+
# If you want to override that behaviour please use the system_argument: **display**
83+
# e.g. **component.with\_breadcrumbs(display: [:block, :block])**
84+
#
6785
def breadcrumbs
6886
breadcrumb_items = [
6987
{ href: "/foo", text: "Foo" },
@@ -75,6 +93,27 @@ def breadcrumbs
7593
header.with_breadcrumbs(breadcrumb_items)
7694
end
7795
end
96+
97+
# @label With parent link (on narrow)
98+
# **Parent link** is only shown on **narrow screens** by default.
99+
# If you want to override that behaviour please use the system_argument: **display**
100+
# e.g. **component.with\_parent\_link(display: [:block, :block])**
101+
#
102+
def parent_link
103+
render(Primer::OpenProject::PageHeader.new) do |header|
104+
header.with_title { "A title" }
105+
header.with_parent_link(href: "test") { "Parent link" }
106+
end
107+
end
108+
109+
# @label With context bar actions (on narrow)
110+
# **Context bar actions** are only shown on **narrow screens** by default.
111+
# If you want to override that behaviour please use the system_argument: **display**
112+
# e.g. **component.with\_context\_bar\_actions(display: [:block, :block])**
113+
#
114+
def context_bar_actions
115+
render_with_template(locals: {})
116+
end
78117
end
79118
end
80119
end
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<%= render(Primer::OpenProject::PageHeader.new) do |component| %>
2+
<% component.with_title(tag: :h1) do %>
3+
A title
4+
<% end %>
5+
<% component.with_description do %>
6+
A description with actions
7+
<% end %>
8+
<% component.with_parent_link(href: "#") do %>
9+
Parent link
10+
<% end %>
11+
<% component.with_context_bar_actions do %>
12+
<%= render(Primer::Alpha::ActionMenu.new) do |component| %>
13+
<% component.with_show_button { "Menu" } %>
14+
<% component.with_item(label: "Item", tag: :button, value: "") %>
15+
<% component.with_item(
16+
label: "Show dialog",
17+
tag: :button,
18+
content_arguments: { "data-show-dialog-id": "my-dialog" },
19+
value: "",
20+
scheme: :danger
21+
) %>
22+
<% end %>
23+
<% end %>
24+
<% end %>
25+
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<%= render Primer::OpenProject::PageHeader.new do |header| %>
2+
<%= header.with_title(variant: variant) { title } %>
3+
<%= header.with_description { description } %>
4+
<%= header.with_back_button(href: "#", size: back_button_size, 'aria-label': "Back") if with_back_button %>
5+
<%= header.with_breadcrumbs(breadcrumb_items) if with_breadcrumbs %>
6+
<%= header.with_parent_link(href: "#") { "Parent link" } if with_parent_link %>
7+
<% if with_actions %>
8+
<% header.with_actions do %>
9+
<%= render(Primer::Alpha::ActionMenu.new) do |component| %>
10+
<% component.with_show_button { "Menu" } %>
11+
<% component.with_item(label: "Item", tag: :button, value: "") %>
12+
<% component.with_item(
13+
label: "Show dialog",
14+
tag: :button,
15+
content_arguments: { "data-show-dialog-id": "my-dialog" },
16+
value: "",
17+
scheme: :danger
18+
) %>
19+
<% end %>
20+
<% end %>
21+
<% end %>
22+
<% if with_context_bar_actions %>
23+
<% header.with_context_bar_actions do %>
24+
<%= render(Primer::Beta::IconButton.new(
25+
scheme: :default,
26+
size: :small,
27+
icon: "pencil",
28+
"aria-label": "aria_label"
29+
)) %>
30+
<% end %>
31+
<% end %>
32+
<% end %>

test/components/primer/open_project/page_header_test.rb

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,4 +82,26 @@ def test_renders_breadcrumbs
8282
assert_selector("nav[aria-label='Breadcrumb'].PageHeader-breadcrumbs .breadcrumb-item a[href='/foo/bar']")
8383
assert_selector("nav[aria-label='Breadcrumb'].PageHeader-breadcrumbs .breadcrumb-item a[href='#']")
8484
end
85+
86+
def test_renders_parent_link
87+
render_inline(Primer::OpenProject::PageHeader.new) do |header|
88+
header.with_title { "Hello" }
89+
header.with_parent_link(href: "test") { "Parent link" }
90+
end
91+
92+
assert_text("Hello")
93+
assert_selector(".PageHeader-title")
94+
assert_selector(".PageHeader-parentLink")
95+
end
96+
97+
def test_renders_context_bar_actions
98+
render_inline(Primer::OpenProject::PageHeader.new) do |header|
99+
header.with_title { "Hello" }
100+
header.with_context_bar_actions { "An context bar action" }
101+
end
102+
103+
assert_text("Hello")
104+
assert_selector(".PageHeader-title")
105+
assert_selector(".PageHeader-contextBarActions")
106+
end
85107
end

0 commit comments

Comments
 (0)