openproject-primer_view_components 0.31.0 → 0.32.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (37) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +12 -0
  3. data/app/assets/javascripts/app/components/primer/open_project/sub_header_element.d.ts +13 -0
  4. data/app/assets/javascripts/app/components/primer/primer.d.ts +1 -0
  5. data/app/assets/javascripts/primer_view_components.js +1 -1
  6. data/app/assets/javascripts/primer_view_components.js.map +1 -1
  7. data/app/assets/styles/primer_view_components.css +1 -1
  8. data/app/assets/styles/primer_view_components.css.map +1 -1
  9. data/app/components/primer/open_project/page_header.rb +1 -1
  10. data/app/components/primer/open_project/sub_header.css +1 -0
  11. data/app/components/primer/open_project/sub_header.css.json +11 -0
  12. data/app/components/primer/open_project/sub_header.css.map +1 -0
  13. data/app/components/primer/open_project/sub_header.html.erb +25 -0
  14. data/app/components/primer/open_project/sub_header.pcss +42 -0
  15. data/app/components/primer/open_project/sub_header.rb +140 -0
  16. data/app/components/primer/open_project/sub_header_element.d.ts +13 -0
  17. data/app/components/primer/open_project/sub_header_element.js +44 -0
  18. data/app/components/primer/open_project/sub_header_element.ts +45 -0
  19. data/app/components/primer/primer.d.ts +1 -0
  20. data/app/components/primer/primer.js +1 -0
  21. data/app/components/primer/primer.pcss +1 -0
  22. data/app/components/primer/primer.ts +1 -0
  23. data/lib/primer/view_components/version.rb +2 -2
  24. data/previews/primer/open_project/sub_header_preview/action_menu_buttons.html.erb +15 -0
  25. data/previews/primer/open_project/sub_header_preview/bottom_pane.html.erb +12 -0
  26. data/previews/primer/open_project/sub_header_preview/button_group.html.erb +11 -0
  27. data/previews/primer/open_project/sub_header_preview/custom_filter_button.html.erb +8 -0
  28. data/previews/primer/open_project/sub_header_preview/dialog_buttons.html.erb +12 -0
  29. data/previews/primer/open_project/sub_header_preview.rb +88 -0
  30. data/static/arguments.json +16 -0
  31. data/static/audited_at.json +1 -0
  32. data/static/classes.json +18 -0
  33. data/static/constants.json +4 -0
  34. data/static/info_arch.json +171 -0
  35. data/static/previews.json +112 -0
  36. data/static/statuses.json +1 -0
  37. metadata +18 -2
@@ -250,7 +250,7 @@ module Primer
250
250
 
251
251
  private
252
252
 
253
- def set_action_arguments(system_arguments, scheme: nil, button_action: false)
253
+ def set_action_arguments(system_arguments, scheme: nil)
254
254
  system_arguments[:ml] ||= 2
255
255
  system_arguments[:display] = [:none, :flex]
256
256
  system_arguments[:size] = :medium
@@ -0,0 +1 @@
1
+ .SubHeader{align-items:center;display:grid;flex-wrap:wrap;grid-template-areas:"left middle right" "bottom bottom bottom";grid-template-columns:auto 1fr auto;margin-bottom:16px}.SubHeader-rightPane{align-items:center;column-gap:12px;display:flex;grid-area:right}.SubHeader-middlePane{grid-area:middle;text-align:center}.SubHeader-bottomPane{grid-area:bottom}.SubHeader-leftPane{align-items:center;display:flex;gap:12px;grid-area:left;width:100%}.SubHeader-filterContainer{display:flex;gap:8px;width:100%}
@@ -0,0 +1,11 @@
1
+ {
2
+ "name": "open_project/sub_header",
3
+ "selectors": [
4
+ ".SubHeader",
5
+ ".SubHeader-rightPane",
6
+ ".SubHeader-middlePane",
7
+ ".SubHeader-bottomPane",
8
+ ".SubHeader-leftPane",
9
+ ".SubHeader-filterContainer"
10
+ ]
11
+ }
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["sub_header.pcss"],"names":[],"mappings":"AAEA,WAII,kBAAmB,CAHnB,YAAa,CAOb,cAAe,CANf,8DAA+D,CAC/D,mCAAoC,CAEpC,kBAIJ,CAEA,qBAGI,kBAAmB,CACnB,eAAgB,CAFhB,YAAa,CADb,eAIJ,CAEA,sBACI,gBAAiB,CACjB,iBACJ,CAEA,sBACI,gBACJ,CAEA,oBAGI,kBAAmB,CADnB,YAAa,CAGb,QAAS,CAJT,cAAe,CAGf,UAEJ,CAEA,2BACI,YAAa,CAEb,OAAQ,CADR,UAEJ","file":"sub_header.css","sourcesContent":["/* CSS for SubHeader */\n\n.SubHeader {\n display: grid;\n grid-template-areas: \"left middle right\" \"bottom bottom bottom\";\n grid-template-columns: auto 1fr auto;\n align-items: center;\n margin-bottom: 16px;\n\n /* When the filter input is expanded in mobile, we switch to a flex layout */\n flex-wrap: wrap;\n}\n\n.SubHeader-rightPane {\n grid-area: right;\n display: flex;\n align-items: center;\n column-gap: 12px;\n}\n\n.SubHeader-middlePane {\n grid-area: middle;\n text-align: center;\n}\n\n.SubHeader-bottomPane {\n grid-area: bottom;\n}\n\n.SubHeader-leftPane {\n grid-area: left;\n display: flex;\n align-items: center;\n width: 100%;\n gap: 12px;\n}\n\n.SubHeader-filterContainer {\n display: flex;\n width: 100%;\n gap: 8px;\n}\n"]}
@@ -0,0 +1,25 @@
1
+ <%= render Primer::BaseComponent.new(**@system_arguments) do %>
2
+ <div class="SubHeader-leftPane">
3
+ <%= render @filter_container do %>
4
+ <%= filter_input %>
5
+ <%= render @mobile_filter_cancel do
6
+ I18n.t("button_cancel")
7
+ end if @mobile_filter_cancel.present? %>
8
+ <% end if filter_input.present? %>
9
+ <%= render @mobile_filter_trigger if @mobile_filter_trigger.present? %>
10
+ <%= filter_button %>
11
+ </div>
12
+ <div class="SubHeader-middlePane" data-targets="<%= HIDDEN_FILTER_TARGET_SELECTOR %>">
13
+ <%= text %>
14
+ </div>
15
+ <div class="SubHeader-rightPane" data-targets="<%= HIDDEN_FILTER_TARGET_SELECTOR %>">
16
+ <% actions.each do |action| %>
17
+ <%= action %>
18
+ <% end %>
19
+ </div>
20
+ <% if bottom_pane_component.present? %>
21
+ <div class="SubHeader-bottomPane">
22
+ <%= bottom_pane_component %>
23
+ </div>
24
+ <% end %>
25
+ <% end %>
@@ -0,0 +1,42 @@
1
+ /* CSS for SubHeader */
2
+
3
+ .SubHeader {
4
+ display: grid;
5
+ grid-template-areas: "left middle right" "bottom bottom bottom";
6
+ grid-template-columns: auto 1fr auto;
7
+ align-items: center;
8
+ margin-bottom: 16px;
9
+
10
+ /* When the filter input is expanded in mobile, we switch to a flex layout */
11
+ flex-wrap: wrap;
12
+ }
13
+
14
+ .SubHeader-rightPane {
15
+ grid-area: right;
16
+ display: flex;
17
+ align-items: center;
18
+ column-gap: 12px;
19
+ }
20
+
21
+ .SubHeader-middlePane {
22
+ grid-area: middle;
23
+ text-align: center;
24
+ }
25
+
26
+ .SubHeader-bottomPane {
27
+ grid-area: bottom;
28
+ }
29
+
30
+ .SubHeader-leftPane {
31
+ grid-area: left;
32
+ display: flex;
33
+ align-items: center;
34
+ width: 100%;
35
+ gap: 12px;
36
+ }
37
+
38
+ .SubHeader-filterContainer {
39
+ display: flex;
40
+ width: 100%;
41
+ gap: 8px;
42
+ }
@@ -0,0 +1,140 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Primer
4
+ module OpenProject
5
+ # The SubHeader contains specific actions to modify the page content below, e.g a filter button or a create button
6
+ # It should not be used stand alone, but in combination with a PageHeader, either as a direct sibling or as part of a tab content
7
+ class SubHeader < Primer::Component
8
+ status :open_project
9
+
10
+ HIDDEN_FILTER_TARGET_SELECTOR = "sub-header.hiddenItemsOnExpandedFilter"
11
+ SHOWN_FILTER_TARGET_SELECTOR = "sub-header.shownItemsOnExpandedFilter"
12
+
13
+ # A button or custom content that will render on the right-hand side of the component.
14
+ #
15
+ # To render a button, call the `with_button` method, which accepts the arguments accepted by <%= link_to_component(Primer::Beta::Button) %>.
16
+ #
17
+ # To render custom content, call the `with_button_component` method and pass a block that returns HTML.
18
+ renders_many :actions, types: {
19
+ button: {
20
+ renders: lambda { |icon: nil, **kwargs|
21
+ if icon
22
+ Primer::Beta::IconButton.new(icon: icon, **kwargs)
23
+ else
24
+ Primer::Beta::Button.new(**kwargs)
25
+ end
26
+ },
27
+ },
28
+ component: {
29
+ # A generic slot to render whatever component you like on the right side
30
+ renders: lambda { |**kwargs|
31
+ deny_tag_argument(**kwargs)
32
+ kwargs[:tag] = :div
33
+ Primer::BaseComponent.new(**kwargs)
34
+ },
35
+ }
36
+ }
37
+
38
+ renders_one :filter_input, lambda { |name:, label:, **system_arguments|
39
+ system_arguments[:classes] = class_names(
40
+ system_arguments[:classes],
41
+ "SubHeader-filterInput"
42
+ )
43
+ system_arguments[:placeholder] ||= I18n.t("button_filter")
44
+ system_arguments[:leading_visual] ||= { icon: :search }
45
+ system_arguments[:visually_hide_label] ||= true
46
+
47
+ system_arguments[:data] ||= {}
48
+ system_arguments[:data][:target]= "sub-header.filterInput"
49
+
50
+
51
+ @mobile_filter_trigger = Primer::Beta::IconButton.new(icon: system_arguments[:leading_visual][:icon],
52
+ display: [:inline_flex, :none],
53
+ aria: {label: label },
54
+ "data-action": "click:sub-header#expandFilterInput",
55
+ "data-targets": HIDDEN_FILTER_TARGET_SELECTOR)
56
+
57
+ @mobile_filter_cancel = Primer::Beta::Button.new(scheme: :invisible,
58
+ display: :none,
59
+ data: {
60
+ targets: SHOWN_FILTER_TARGET_SELECTOR,
61
+ action: "click:sub-header#collapseFilterInput"})
62
+
63
+
64
+ Primer::Alpha::TextField.new(name: name, label: label, **system_arguments)
65
+ }
66
+
67
+
68
+ # A button or custom content that will render on the left-hand side of the component, next to the filter input.
69
+ #
70
+ # To render a button, call the `with_filter_button` method, which accepts the arguments accepted by <%= link_to_component(Primer::Beta::Button) %>.
71
+ #
72
+ # To render custom content, call the `with_filter_component` method and pass a block that returns HTML.
73
+ renders_one :filter_button, types: {
74
+ button: {
75
+ renders: lambda { |icon: nil, **kwargs|
76
+ kwargs[:classes] = class_names(
77
+ kwargs[:classes],
78
+ "SubHeader-filterButton"
79
+ )
80
+ kwargs[:data] ||= {}
81
+ kwargs[:data][:targets] ||= HIDDEN_FILTER_TARGET_SELECTOR
82
+
83
+ if icon
84
+ Primer::Beta::IconButton.new(icon: icon, **kwargs)
85
+ else
86
+ Primer::Beta::Button.new(**kwargs)
87
+ end
88
+ },
89
+
90
+ as: :filter_button
91
+ },
92
+ component: {
93
+ # A generic slot to render a custom filter component
94
+ renders: lambda { |**kwargs|
95
+ deny_tag_argument(**kwargs)
96
+ kwargs[:tag] = :div
97
+ kwargs[:data] ||= {}
98
+ kwargs[:data][:targets] ||= HIDDEN_FILTER_TARGET_SELECTOR
99
+
100
+ Primer::BaseComponent.new(**kwargs)
101
+ },
102
+
103
+ as: :filter_component
104
+ }
105
+ }
106
+
107
+ renders_one :text, lambda { |**system_arguments|
108
+ system_arguments[:font_weight] ||= :bold
109
+
110
+ Primer::Beta::Text.new(**system_arguments)
111
+ }
112
+
113
+ # A slot for a generic component which will be shown in a second row below the rest, spanning the whole width
114
+ renders_one :bottom_pane_component, lambda { |**system_arguments|
115
+ deny_tag_argument(**system_arguments)
116
+ system_arguments[:tag] = :div
117
+ system_arguments[:mt] ||= 3
118
+
119
+ Primer::BaseComponent.new(**system_arguments)
120
+ }
121
+
122
+
123
+ # @param system_arguments [Hash] <%= link_to_system_arguments_docs %>
124
+ def initialize(**system_arguments)
125
+ @system_arguments = system_arguments
126
+ @system_arguments[:tag] = :"sub-header"
127
+
128
+ @filter_container = Primer::BaseComponent.new(tag: :div,
129
+ classes: "SubHeader-filterContainer",
130
+ display: [:none, :flex],
131
+ data: { targets: SHOWN_FILTER_TARGET_SELECTOR })
132
+
133
+ @system_arguments[:classes] = class_names(
134
+ "SubHeader",
135
+ system_arguments[:classes]
136
+ )
137
+ end
138
+ end
139
+ end
140
+ end
@@ -0,0 +1,13 @@
1
+ declare class SubHeaderElement extends HTMLElement {
2
+ filterInput: HTMLElement;
3
+ hiddenItemsOnExpandedFilter: HTMLElement[];
4
+ shownItemsOnExpandedFilter: HTMLElement[];
5
+ expandFilterInput(): void;
6
+ collapseFilterInput(): void;
7
+ }
8
+ declare global {
9
+ interface Window {
10
+ SubHeaderElement: typeof SubHeaderElement;
11
+ }
12
+ }
13
+ export {};
@@ -0,0 +1,44 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ import { controller, target, targets } from '@github/catalyst';
8
+ let SubHeaderElement = class SubHeaderElement extends HTMLElement {
9
+ expandFilterInput() {
10
+ for (const item of this.hiddenItemsOnExpandedFilter) {
11
+ item.classList.add('d-none');
12
+ }
13
+ for (const item of this.shownItemsOnExpandedFilter) {
14
+ item.classList.remove('d-none');
15
+ }
16
+ this.classList.add('d-flex');
17
+ this.filterInput.focus();
18
+ }
19
+ collapseFilterInput() {
20
+ for (const item of this.hiddenItemsOnExpandedFilter) {
21
+ item.classList.remove('d-none');
22
+ }
23
+ for (const item of this.shownItemsOnExpandedFilter) {
24
+ item.classList.add('d-none');
25
+ }
26
+ this.classList.remove('d-flex');
27
+ }
28
+ };
29
+ __decorate([
30
+ target
31
+ ], SubHeaderElement.prototype, "filterInput", void 0);
32
+ __decorate([
33
+ targets
34
+ ], SubHeaderElement.prototype, "hiddenItemsOnExpandedFilter", void 0);
35
+ __decorate([
36
+ targets
37
+ ], SubHeaderElement.prototype, "shownItemsOnExpandedFilter", void 0);
38
+ SubHeaderElement = __decorate([
39
+ controller
40
+ ], SubHeaderElement);
41
+ if (!window.customElements.get('sub-header')) {
42
+ window.SubHeaderElement = SubHeaderElement;
43
+ window.customElements.define('sub-header', SubHeaderElement);
44
+ }
@@ -0,0 +1,45 @@
1
+ import {controller, target, targets} from '@github/catalyst'
2
+
3
+ @controller
4
+ class SubHeaderElement extends HTMLElement {
5
+ @target filterInput: HTMLElement
6
+ @targets hiddenItemsOnExpandedFilter: HTMLElement[]
7
+ @targets shownItemsOnExpandedFilter: HTMLElement[]
8
+
9
+ expandFilterInput() {
10
+ for (const item of this.hiddenItemsOnExpandedFilter) {
11
+ item.classList.add('d-none')
12
+ }
13
+
14
+ for (const item of this.shownItemsOnExpandedFilter) {
15
+ item.classList.remove('d-none')
16
+ }
17
+
18
+ this.classList.add('d-flex')
19
+
20
+ this.filterInput.focus()
21
+ }
22
+
23
+ collapseFilterInput() {
24
+ for (const item of this.hiddenItemsOnExpandedFilter) {
25
+ item.classList.remove('d-none')
26
+ }
27
+
28
+ for (const item of this.shownItemsOnExpandedFilter) {
29
+ item.classList.add('d-none')
30
+ }
31
+
32
+ this.classList.remove('d-flex')
33
+ }
34
+ }
35
+
36
+ declare global {
37
+ interface Window {
38
+ SubHeaderElement: typeof SubHeaderElement
39
+ }
40
+ }
41
+
42
+ if (!window.customElements.get('sub-header')) {
43
+ window.SubHeaderElement = SubHeaderElement
44
+ window.customElements.define('sub-header', SubHeaderElement)
45
+ }
@@ -24,3 +24,4 @@ import '../../../lib/primer/forms/toggle_switch_input';
24
24
  import './alpha/action_menu/action_menu_element';
25
25
  import './open_project/page_header_element';
26
26
  import './open_project/zen_mode_button';
27
+ import './open_project/sub_header_element';
@@ -24,3 +24,4 @@ import '../../../lib/primer/forms/toggle_switch_input';
24
24
  import './alpha/action_menu/action_menu_element';
25
25
  import './open_project/page_header_element';
26
26
  import './open_project/zen_mode_button';
27
+ import './open_project/sub_header_element';
@@ -44,3 +44,4 @@
44
44
  @import "./open_project/drag_handle.pcss";
45
45
  @import "./open_project/border_grid.pcss";
46
46
  @import "./open_project/input_group.pcss";
47
+ @import "./open_project/sub_header.pcss";
@@ -24,3 +24,4 @@ import '../../../lib/primer/forms/toggle_switch_input'
24
24
  import './alpha/action_menu/action_menu_element'
25
25
  import './open_project/page_header_element'
26
26
  import './open_project/zen_mode_button'
27
+ import './open_project/sub_header_element'
@@ -5,8 +5,8 @@ module Primer
5
5
  module ViewComponents
6
6
  module VERSION
7
7
  MAJOR = 0
8
- MINOR = 31
9
- PATCH = 0
8
+ MINOR = 32
9
+ PATCH = 1
10
10
 
11
11
  STRING = [MAJOR, MINOR, PATCH].join(".")
12
12
  end
@@ -0,0 +1,15 @@
1
+ <%= render(Primer::OpenProject::SubHeader.new) do |component| %>
2
+ <% component.with_filter_input(name: "filter", label: "Filter") %>
3
+
4
+ <% component.with_action_component do %>
5
+ <%= render Primer::Alpha::ActionMenu.new(menu_id: "menu-1") do |menu|
6
+ menu.with_show_button(icon: :"op-kebab-vertical", "aria-label": "Menu")
7
+ menu.with_item(label: "Subitem 1") do |item|
8
+ item.with_leading_visual_icon(icon: :paste)
9
+ end
10
+ menu.with_item(label: "Subitem 2") do |item|
11
+ item.with_leading_visual_icon(icon: :log)
12
+ end
13
+ end %>
14
+ <% end %>
15
+ <% end %>
@@ -0,0 +1,12 @@
1
+ <%= render(Primer::OpenProject::SubHeader.new) do |component| %>
2
+ <% component.with_filter_input(name: "filter", label: "Filter") %>
3
+ <% component.with_filter_component do %>
4
+ <!-- Render any custom filter component that you want -->
5
+ <%= render(Primer::Beta::IconButton.new(icon: "filter", "aria-label": "Filter")) %>
6
+ <% end %>
7
+ <% component.with_bottom_pane_component do %>
8
+ <!-- Render any custom component that you want -->
9
+ <!-- The component will be shown in a second row below the rest, spanning the whole width -->
10
+ <%= render(Primer::BaseComponent.new(tag: :div, bg: :accent, p: 3)) { 'Render any custom content here (e.g a filter area)' } %>
11
+ <% end %>
12
+ <% end %>
@@ -0,0 +1,11 @@
1
+ <%= render(Primer::OpenProject::SubHeader.new) do |component| %>
2
+ <% component.with_filter_input(name: "filter", label: "Filter") %>
3
+
4
+ <% component.with_action_component do %>
5
+ <%= render(Primer::Beta::ButtonGroup.new) do |group|
6
+ group.with_button { "Button 1" }
7
+ group.with_button { "Button 2" }
8
+ group.with_button { "Button 3" }
9
+ end %>
10
+ <% end %>
11
+ <% end %>
@@ -0,0 +1,8 @@
1
+ <%= render(Primer::OpenProject::SubHeader.new) do |component| %>
2
+ <% component.with_filter_input(name: "filter", label: "Filter") %>
3
+ <% component.with_filter_component do %>
4
+ <!-- Render any custom filter component that you want -->
5
+ <!-- Note, that you can pass an ID for the bottom pane if you need to access that area for further filter actions-->
6
+ <%= render(Primer::Beta::IconButton.new(icon: "filter", "aria-label": "Filter")) %>
7
+ <% end %>
8
+ <% end %>
@@ -0,0 +1,12 @@
1
+ <%= render(Primer::OpenProject::SubHeader.new) do |component| %>
2
+ <% component.with_filter_input(name: "filter", label: "Filter") %>
3
+
4
+ <% component.with_action_component do %>
5
+ <%= render(Primer::Alpha::Dialog.new(id: "dialog-one", title: "Dialog")) do |d| %>
6
+ <% d.with_show_button { "Show Dialog" } %>
7
+ <% d.with_body do %>
8
+ Hello world!
9
+ <% end %>
10
+ <% end %>
11
+ <% end %>
12
+ <% end %>
@@ -0,0 +1,88 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Setup Playground to use all available component props
4
+ # Setup Features to use individual component props and combinations
5
+
6
+ module Primer
7
+ module OpenProject
8
+ # @label SubHeader
9
+ class SubHeaderPreview < ViewComponent::Preview
10
+ # @label Playground
11
+ # @param show_filter_input toggle
12
+ # @param show_filter_button toggle
13
+ # @param show_action_button toggle
14
+ # @param text text
15
+ def playground(show_filter_input: true, show_filter_button: true, show_action_button: true, text: nil)
16
+ render(Primer::OpenProject::SubHeader.new) do |component|
17
+ component.with_filter_input(name: "filter", label: "Filter") if show_filter_input
18
+ component.with_filter_button do |button|
19
+ button.with_trailing_visual_counter(count: "15")
20
+ "Filter"
21
+ end if show_filter_button
22
+
23
+ component.with_text { text } unless text.nil?
24
+
25
+ component.with_action_button(scheme: :primary) do |button|
26
+ button.with_leading_visual_icon(icon: :plus)
27
+ "Create"
28
+ end if show_action_button
29
+ end
30
+ end
31
+
32
+ # @label Default
33
+ def default
34
+ render(Primer::OpenProject::SubHeader.new) do |component|
35
+ component.with_filter_input(name: "filter", label: "Filter")
36
+ component.with_filter_button do |button|
37
+ button.with_trailing_visual_counter(count: "15")
38
+ "Filter"
39
+ end
40
+
41
+ component.with_action_button(scheme: :primary) do |button|
42
+ button.with_leading_visual_icon(icon: :plus)
43
+ "Create"
44
+ end
45
+ end
46
+ end
47
+
48
+ # @label With ActionMenu
49
+ def action_menu_buttons
50
+ render_with_template(locals: {})
51
+ end
52
+
53
+ # @label With Dialog
54
+ def dialog_buttons
55
+ render_with_template(locals: {})
56
+ end
57
+
58
+ # @label With ButtonGroup
59
+ def button_group
60
+ render_with_template(locals: {})
61
+ end
62
+
63
+ # @label With custom filter button
64
+ def custom_filter_button
65
+ render_with_template(locals: {})
66
+ end
67
+
68
+ # @label With a custom area below
69
+ def bottom_pane
70
+ render_with_template(locals: {})
71
+ end
72
+
73
+ # @label With Text in the middle
74
+ def text
75
+ render(Primer::OpenProject::SubHeader.new) do |component|
76
+ component.with_filter_input(name: "filter", label: "Filter")
77
+
78
+ component.with_text { "Hello world!" }
79
+
80
+ component.with_action_button(scheme: :primary) do |button|
81
+ button.with_leading_visual_icon(icon: :plus)
82
+ "Create"
83
+ end
84
+ end
85
+ end
86
+ end
87
+ end
88
+ end
@@ -5023,6 +5023,22 @@
5023
5023
  }
5024
5024
  ]
5025
5025
  },
5026
+ {
5027
+ "component": "OpenProject::SubHeader",
5028
+ "status": "open_project",
5029
+ "a11y_reviewed": false,
5030
+ "short_name": "OpenProjectSubHeader",
5031
+ "source": "https://github.com/primer/view_components/tree/main/app/components/primer/open_project/sub_header.rb",
5032
+ "lookbook": "https://primer.style/view-components/lookbook/inspect/primer/open_project/sub_header/default/",
5033
+ "parameters": [
5034
+ {
5035
+ "name": "system_arguments",
5036
+ "type": "Hash",
5037
+ "default": "N/A",
5038
+ "description": "[System arguments](/system-arguments)"
5039
+ }
5040
+ ]
5041
+ },
5026
5042
  {
5027
5043
  "component": "OpenProject::ZenModeButton",
5028
5044
  "status": "open_project",
@@ -123,6 +123,7 @@
123
123
  "Primer::OpenProject::PageHeader": "",
124
124
  "Primer::OpenProject::PageHeader::Dialog": "",
125
125
  "Primer::OpenProject::PageHeader::Menu": "",
126
+ "Primer::OpenProject::SubHeader": "",
126
127
  "Primer::OpenProject::ZenModeButton": "",
127
128
  "Primer::Tooltip": "",
128
129
  "Primer::Truncate": ""
data/static/classes.json CHANGED
@@ -555,6 +555,24 @@
555
555
  "State--small": [
556
556
  "Primer::Beta::State"
557
557
  ],
558
+ "SubHeader": [
559
+ "Primer::OpenProject::SubHeader"
560
+ ],
561
+ "SubHeader-bottomPane": [
562
+ "Primer::OpenProject::SubHeader"
563
+ ],
564
+ "SubHeader-filterContainer": [
565
+ "Primer::OpenProject::SubHeader"
566
+ ],
567
+ "SubHeader-leftPane": [
568
+ "Primer::OpenProject::SubHeader"
569
+ ],
570
+ "SubHeader-middlePane": [
571
+ "Primer::OpenProject::SubHeader"
572
+ ],
573
+ "SubHeader-rightPane": [
574
+ "Primer::OpenProject::SubHeader"
575
+ ],
558
576
  "Subhead": [
559
577
  "Primer::Beta::Subhead"
560
578
  ],
@@ -1473,6 +1473,10 @@
1473
1473
  },
1474
1474
  "Primer::OpenProject::PageHeader::Menu": {
1475
1475
  },
1476
+ "Primer::OpenProject::SubHeader": {
1477
+ "HIDDEN_FILTER_TARGET_SELECTOR": "sub-header.hiddenItemsOnExpandedFilter",
1478
+ "SHOWN_FILTER_TARGET_SELECTOR": "sub-header.shownItemsOnExpandedFilter"
1479
+ },
1476
1480
  "Primer::OpenProject::ZenModeButton": {
1477
1481
  "ZEN_MODE_BUTTON_ICON": "screen-full",
1478
1482
  "ZEN_MODE_BUTTON_LABEL": "Translation missing: en.label_zen_mode"