Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat[#51013]: Extend page header with parent link, context bar actions and responsiveness #49

Merged
merged 9 commits into from
Nov 17, 2023
Merged
5 changes: 5 additions & 0 deletions .changeset/giant-carrots-explain.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@openproject/primer-view-components': minor
---

Extend page header with parent link, context bar actions and responsiveness
10 changes: 9 additions & 1 deletion app/components/primer/open_project/page_header.html.erb
Original file line number Diff line number Diff line change
@@ -1,9 +1,17 @@
<%= render Primer::BaseComponent.new(**@system_arguments) do %>
<%= breadcrumbs %>
<% if parent_link || breadcrumbs || context_bar_actions %>
<div class="PageHeader-contextBar">
<%= parent_link %>
<%= breadcrumbs %>
<%= context_bar_actions %>
</div>
<% end %>

<div class="PageHeader-titleBar">
<%= back_button %>
<%= title %>
<%= actions %>
</div>

<%= description %>
<% end %>
20 changes: 19 additions & 1 deletion app/components/primer/open_project/page_header.pcss
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,13 @@
}
}

.PageHeader-contextBar {
display: flex;
flex-flow: row;
justify-content: flex-end;
align-items: center;
}

.PageHeader-titleBar {
display: flex;
flex-flow: row;
Expand All @@ -38,8 +45,9 @@

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

& + .PageHeader-description {
margin-top: var(--base-size-4);
Expand All @@ -50,9 +58,19 @@
display: block;
width: 100%;
margin-bottom: var(--base-size-8);
padding-bottom: var(--base-size-4);
}

.PageHeader-backButton {
margin-top: 2px; /* to center align with label */
margin-right: var(--base-size-4);
}

.PageHeader-parentLink {
flex: 1 1 auto;
margin-bottom: var(--base-size-4);
}

.PageHeader-contextBarActions {
margin: 0 0 0 var(--base-size-4);
}
38 changes: 38 additions & 0 deletions app/components/primer/open_project/page_header.rb
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,11 @@ class PageHeader < Primer::Component
"triangle-left"
].freeze

DEFAULT_BACK_BUTTON_DISPLAY = [:none, :flex].freeze
DEFAULT_BREADCRUMBS_DISPLAY = [:none, :flex].freeze
DEFAULT_PARENT_LINK_DISPLAY = [:block, :none].freeze
DEFAULT_CONTEXT_BAR_ACTIONS_DISPLAY = [:block, :none].freeze

status :open_project

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

# Context Bar Actions
# By default shown on narrow screens. Can be overridden with system_argument: display
#
# @param system_arguments [Hash] <%= link_to_system_arguments_docs %>
renders_one :context_bar_actions, lambda { |**system_arguments|
deny_tag_argument(**system_arguments)
system_arguments[:tag] = :div
system_arguments[:classes] = class_names(system_arguments[:classes], "PageHeader-contextBarActions")
system_arguments[:display] ||= DEFAULT_CONTEXT_BAR_ACTIONS_DISPLAY

Primer::BaseComponent.new(**system_arguments)
}

# Optional back button prepend the title
# By default shown on wider screens. Can be overridden with system_argument: display
#
# @param size [Symbol] <%= one_of(Primer::OpenProject::PageHeader::BACK_BUTTON_SIZE_OPTIONS) %>
# @param icon [String] <%= one_of(Primer::OpenProject::PageHeader::BACK_BUTTON_ICON_OPTIONS) %>
Expand All @@ -80,16 +99,35 @@ class PageHeader < Primer::Component
system_arguments[:size] = fetch_or_fallback(BACK_BUTTON_SIZE_OPTIONS, size, DEFAULT_BACK_BUTTON_SIZE)
system_arguments[:icon] = fetch_or_fallback(BACK_BUTTON_ICON_OPTIONS, icon, DEFAULT_BACK_BUTTON_ICON)
system_arguments[:classes] = class_names(system_arguments[:classes], "PageHeader-backButton")
system_arguments[:display] ||= DEFAULT_BACK_BUTTON_DISPLAY

Primer::Beta::IconButton.new(**system_arguments)
}

# Optional parent link in the context area
dominic-braeunlein marked this conversation as resolved.
Show resolved Hide resolved
# By default shown on narrow screens. Can be overridden with system_argument: display
#
# @param system_arguments [Hash] <%= link_to_system_arguments_docs %>
renders_one :parent_link, lambda { |icon: DEFAULT_BACK_BUTTON_ICON, **system_arguments, &block|
deny_tag_argument(**system_arguments)
system_arguments[:icon] = fetch_or_fallback(BACK_BUTTON_ICON_OPTIONS, icon, DEFAULT_BACK_BUTTON_ICON)
system_arguments[:classes] = class_names(system_arguments[:classes], "PageHeader-parentLink")
system_arguments[:display] ||= DEFAULT_PARENT_LINK_DISPLAY

render(Primer::Beta::Link.new(scheme: :primary, muted: true, **system_arguments)) do
render(Primer::Beta::Octicon.new(icon: "arrow-left", "aria-label": "aria_label", mr: 2)) + content_tag(:span, &block)
end
}

# Optional breadcrumbs above the title row
# By default shown on wider screens. Can be overridden with system_argument: display
#
# @param items [Array<String, Hash>] Items is an array of strings, hash {href, text} or an anchor tag string
# @param system_arguments [Hash] <%= link_to_system_arguments_docs %>
renders_one :breadcrumbs, lambda { |items, **system_arguments|
system_arguments[:classes] = class_names(system_arguments[:classes], "PageHeader-breadcrumbs")
system_arguments[:display] ||= DEFAULT_BREADCRUMBS_DISPLAY

render(Primer::Beta::Breadcrumbs.new(**system_arguments)) do |breadcrumbs|
items.each do |item|
item = anchor_string_to_object(item) if anchor_tag_string?(item)
Expand Down
57 changes: 48 additions & 9 deletions previews/primer/open_project/page_header_preview.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,22 +21,32 @@ def default
# @param with_back_button [Boolean]
# @param back_button_size [Symbol] select [small, medium, large]
# @param with_breadcrumbs [Boolean]
# @param with_actions [Boolean]
# @param with_context_bar_actions [Boolean]
# @param with_parent_link [Boolean]
def playground(
variant: :medium,
title: "Hello",
description: "Last updated 5 minutes ago by XYZ.",
with_back_button: false,
back_button_size: :medium,
with_breadcrumbs: false
with_breadcrumbs: false,
with_actions: false,
with_context_bar_actions: false,
with_parent_link: false
)
breadcrumb_items = [{ href: "/foo", text: "Foo" }, { href: "/bar", text: "Bar" }, "Baz"]

render(Primer::OpenProject::PageHeader.new) do |header|
header.with_title(variant: variant) { title }
header.with_description { description }
header.with_back_button(href: "#", size: back_button_size, 'aria-label': "Back") if with_back_button
header.with_breadcrumbs(breadcrumb_items) if with_breadcrumbs
end
render_with_template(locals: { variant: variant,
title: title,
description: description,
with_back_button: with_back_button,
back_button_size: back_button_size,
with_breadcrumbs: with_breadcrumbs,
with_parent_link: with_parent_link,
with_actions: with_actions,
with_context_bar_actions: with_context_bar_actions,
breadcrumb_items: breadcrumb_items })
end

# @label Large
Expand All @@ -52,7 +62,11 @@ def actions
render_with_template(locals: {})
end

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

# @label With breadcrumbs
# @label With breadcrumbs (on wide)
# **Breadcrumbs** are only shown on **wider than narrow screens** by default.
# If you want to override that behaviour please use the system_argument: **display**
# e.g. **component.with\_breadcrumbs(display: [:block, :block])**
#
def breadcrumbs
breadcrumb_items = [
{ href: "/foo", text: "Foo" },
Expand All @@ -75,6 +93,27 @@ def breadcrumbs
header.with_breadcrumbs(breadcrumb_items)
end
end

# @label With parent link (on narrow)
# **Parent link** is only shown on **narrow screens** by default.
# If you want to override that behaviour please use the system_argument: **display**
# e.g. **component.with\_parent\_link(display: [:block, :block])**
#
def parent_link
render(Primer::OpenProject::PageHeader.new) do |header|
header.with_title { "A title" }
header.with_parent_link(href: "test") { "Parent link" }
end
end

# @label With context bar actions (on narrow)
# **Context bar actions** are only shown on **narrow screens** by default.
# If you want to override that behaviour please use the system_argument: **display**
# e.g. **component.with\_context\_bar\_actions(display: [:block, :block])**
#
def context_bar_actions
render_with_template(locals: {})
end
end
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<%= render(Primer::OpenProject::PageHeader.new) do |component| %>
<% component.with_title(tag: :h1) do %>
A title
<% end %>
<% component.with_description do %>
A description with actions
<% end %>
<% component.with_parent_link(href: "#") do %>
Parent link
<% end %>
<% component.with_context_bar_actions do %>
<%= render(Primer::Alpha::ActionMenu.new) do |component| %>
<% component.with_show_button { "Menu" } %>
<% component.with_item(label: "Item", tag: :button, value: "") %>
<% component.with_item(
label: "Show dialog",
tag: :button,
content_arguments: { "data-show-dialog-id": "my-dialog" },
value: "",
scheme: :danger
) %>
<% end %>
<% end %>
<% end %>

Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<%= render Primer::OpenProject::PageHeader.new do |header| %>
<%= header.with_title(variant: variant) { title } %>
<%= header.with_description { description } %>
<%= header.with_back_button(href: "#", size: back_button_size, 'aria-label': "Back") if with_back_button %>
<%= header.with_breadcrumbs(breadcrumb_items) if with_breadcrumbs %>
<%= header.with_parent_link(href: "#") { "Parent link" } if with_parent_link %>
<% if with_actions %>
<% header.with_actions do %>
<%= render(Primer::Alpha::ActionMenu.new) do |component| %>
<% component.with_show_button { "Menu" } %>
<% component.with_item(label: "Item", tag: :button, value: "") %>
<% component.with_item(
label: "Show dialog",
tag: :button,
content_arguments: { "data-show-dialog-id": "my-dialog" },
value: "",
scheme: :danger
) %>
<% end %>
<% end %>
<% end %>
<% if with_context_bar_actions %>
<% header.with_context_bar_actions do %>
<%= render(Primer::Beta::IconButton.new(
scheme: :default,
size: :small,
icon: "pencil",
"aria-label": "aria_label"
)) %>
<% end %>
<% end %>
<% end %>
22 changes: 22 additions & 0 deletions test/components/primer/open_project/page_header_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -82,4 +82,26 @@ def test_renders_breadcrumbs
assert_selector("nav[aria-label='Breadcrumb'].PageHeader-breadcrumbs .breadcrumb-item a[href='/foo/bar']")
assert_selector("nav[aria-label='Breadcrumb'].PageHeader-breadcrumbs .breadcrumb-item a[href='#']")
end

def test_renders_parent_link
render_inline(Primer::OpenProject::PageHeader.new) do |header|
header.with_title { "Hello" }
header.with_parent_link(href: "test") { "Parent link" }
end

assert_text("Hello")
assert_selector(".PageHeader-title")
assert_selector(".PageHeader-parentLink")
end

def test_renders_context_bar_actions
render_inline(Primer::OpenProject::PageHeader.new) do |header|
header.with_title { "Hello" }
header.with_context_bar_actions { "An context bar action" }
end

assert_text("Hello")
assert_selector(".PageHeader-title")
assert_selector(".PageHeader-contextBarActions")
end
end
Loading