openproject-primer_view_components 0.64.1 → 0.66.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +18 -0
- data/app/assets/javascripts/components/primer/open_project/tree_view/tree_view.d.ts +29 -0
- data/app/assets/javascripts/components/primer/open_project/tree_view/tree_view_icon_pair_element.d.ts +15 -0
- data/app/assets/javascripts/components/primer/open_project/tree_view/tree_view_include_fragment_element.d.ts +9 -0
- data/app/assets/javascripts/components/primer/open_project/tree_view/tree_view_roving_tab_index.d.ts +3 -0
- data/app/assets/javascripts/components/primer/open_project/tree_view/tree_view_sub_tree_node_element.d.ts +38 -0
- data/app/assets/javascripts/components/primer/primer.d.ts +4 -0
- data/app/assets/javascripts/components/primer/shared_events.d.ts +15 -0
- data/app/assets/javascripts/primer_view_components.js +1 -1
- data/app/assets/javascripts/primer_view_components.js.map +1 -1
- data/app/assets/styles/primer_view_components.css +1 -1
- data/app/assets/styles/primer_view_components.css.map +1 -1
- data/app/components/primer/alpha/select_panel.css +1 -1
- data/app/components/primer/alpha/select_panel.css.json +2 -2
- data/app/components/primer/alpha/select_panel.css.map +1 -1
- data/app/components/primer/alpha/select_panel.html.erb +1 -1
- data/app/components/primer/alpha/select_panel.pcss +5 -2
- data/app/components/primer/beta/spinner.html.erb +1 -1
- data/app/components/primer/beta/spinner.rb +2 -0
- data/app/components/primer/open_project/file_tree_view/directory_node.html.erb +5 -0
- data/app/components/primer/open_project/file_tree_view/directory_node.rb +24 -0
- data/app/components/primer/open_project/file_tree_view/file_node.html.erb +2 -0
- data/app/components/primer/open_project/file_tree_view/file_node.rb +14 -0
- data/app/components/primer/open_project/file_tree_view.rb +15 -0
- data/app/components/primer/open_project/page_header.rb +1 -1
- data/app/components/primer/open_project/skeleton_box.css +1 -0
- data/app/components/primer/open_project/skeleton_box.css.json +6 -0
- data/app/components/primer/open_project/skeleton_box.css.map +1 -0
- data/app/components/primer/open_project/skeleton_box.html.erb +1 -0
- data/app/components/primer/open_project/skeleton_box.pcss +30 -0
- data/app/components/primer/open_project/skeleton_box.rb +27 -0
- data/app/components/primer/open_project/sub_header/button.rb +43 -0
- data/app/components/primer/open_project/sub_header/button_group.rb +16 -0
- data/app/components/primer/open_project/sub_header/menu.rb +67 -0
- data/app/components/primer/open_project/sub_header/segmented_control.rb +16 -0
- data/app/components/primer/open_project/sub_header.css +1 -1
- data/app/components/primer/open_project/sub_header.css.json +4 -1
- data/app/components/primer/open_project/sub_header.css.map +1 -1
- data/app/components/primer/open_project/sub_header.html.erb +21 -0
- data/app/components/primer/open_project/sub_header.pcss +29 -3
- data/app/components/primer/open_project/sub_header.rb +105 -21
- data/app/components/primer/open_project/tree_view/icon.html.erb +1 -0
- data/app/components/primer/open_project/tree_view/icon.rb +22 -0
- data/app/components/primer/open_project/tree_view/icon_pair.html.erb +13 -0
- data/app/components/primer/open_project/tree_view/icon_pair.rb +42 -0
- data/app/components/primer/open_project/tree_view/leading_action.html.erb +3 -0
- data/app/components/primer/open_project/tree_view/leading_action.rb +18 -0
- data/app/components/primer/open_project/tree_view/leaf_node.html.erb +18 -0
- data/app/components/primer/open_project/tree_view/leaf_node.rb +96 -0
- data/app/components/primer/open_project/tree_view/loading_failure_message.html.erb +13 -0
- data/app/components/primer/open_project/tree_view/loading_failure_message.rb +31 -0
- data/app/components/primer/open_project/tree_view/node.html.erb +32 -0
- data/app/components/primer/open_project/tree_view/node.rb +155 -0
- data/app/components/primer/open_project/tree_view/skeleton_loader.html.erb +23 -0
- data/app/components/primer/open_project/tree_view/skeleton_loader.rb +36 -0
- data/app/components/primer/open_project/tree_view/spinner_loader.html.erb +20 -0
- data/app/components/primer/open_project/tree_view/spinner_loader.rb +33 -0
- data/app/components/primer/open_project/tree_view/sub_tree.html.erb +21 -0
- data/app/components/primer/open_project/tree_view/sub_tree.rb +106 -0
- data/app/components/primer/open_project/tree_view/sub_tree_container.html.erb +3 -0
- data/app/components/primer/open_project/tree_view/sub_tree_container.rb +39 -0
- data/app/components/primer/open_project/tree_view/sub_tree_node.html.erb +49 -0
- data/app/components/primer/open_project/tree_view/sub_tree_node.rb +172 -0
- data/app/components/primer/open_project/tree_view/tree_view.d.ts +29 -0
- data/app/components/primer/open_project/tree_view/tree_view.js +238 -0
- data/app/components/primer/open_project/tree_view/tree_view.ts +257 -0
- data/app/components/primer/open_project/tree_view/tree_view_icon_pair_element.d.ts +15 -0
- data/app/components/primer/open_project/tree_view/tree_view_icon_pair_element.js +62 -0
- data/app/components/primer/open_project/tree_view/tree_view_icon_pair_element.ts +56 -0
- data/app/components/primer/open_project/tree_view/tree_view_include_fragment_element.d.ts +9 -0
- data/app/components/primer/open_project/tree_view/tree_view_include_fragment_element.js +29 -0
- data/app/components/primer/open_project/tree_view/tree_view_include_fragment_element.ts +29 -0
- data/app/components/primer/open_project/tree_view/tree_view_roving_tab_index.d.ts +3 -0
- data/app/components/primer/open_project/tree_view/tree_view_roving_tab_index.js +126 -0
- data/app/components/primer/open_project/tree_view/tree_view_roving_tab_index.ts +156 -0
- data/app/components/primer/open_project/tree_view/tree_view_sub_tree_node_element.d.ts +38 -0
- data/app/components/primer/open_project/tree_view/tree_view_sub_tree_node_element.js +362 -0
- data/app/components/primer/open_project/tree_view/tree_view_sub_tree_node_element.ts +402 -0
- data/app/components/primer/open_project/tree_view/visual.html.erb +14 -0
- data/app/components/primer/open_project/tree_view/visual.rb +27 -0
- data/app/components/primer/open_project/tree_view.css +1 -0
- data/app/components/primer/open_project/tree_view.css.json +42 -0
- data/app/components/primer/open_project/tree_view.css.map +1 -0
- data/app/components/primer/open_project/tree_view.html.erb +7 -0
- data/app/components/primer/open_project/tree_view.pcss +319 -0
- data/app/components/primer/open_project/tree_view.rb +367 -0
- data/app/components/primer/primer.d.ts +4 -0
- data/app/components/primer/primer.js +4 -0
- data/app/components/primer/primer.pcss +2 -0
- data/app/components/primer/primer.ts +4 -0
- data/app/components/primer/shared_events.d.ts +15 -0
- data/app/components/primer/shared_events.ts +19 -0
- data/app/lib/primer/forms/acts_as_component.rb +1 -12
- data/lib/primer/view_components/version.rb +2 -2
- data/previews/primer/open_project/file_tree_view_preview/default.html.erb +16 -0
- data/previews/primer/open_project/file_tree_view_preview/playground.html.erb +4 -0
- data/previews/primer/open_project/file_tree_view_preview.rb +69 -0
- data/previews/primer/open_project/page_header_preview/create_action.html.erb +1 -2
- data/previews/primer/open_project/skeleton_box_preview.rb +20 -0
- data/previews/primer/open_project/sub_header_preview/action_menu_buttons.html.erb +7 -10
- data/previews/primer/open_project/sub_header_preview/button_group.html.erb +13 -7
- data/previews/primer/open_project/sub_header_preview/custom_filter_button.html.erb +1 -1
- data/previews/primer/open_project/sub_header_preview/dialog_buttons.html.erb +9 -8
- data/previews/primer/open_project/sub_header_preview.rb +26 -7
- data/previews/primer/open_project/tree_view_preview/default.html.erb +24 -0
- data/previews/primer/open_project/tree_view_preview/empty.html.erb +10 -0
- data/previews/primer/open_project/tree_view_preview/leaf_node_playground.html.erb +15 -0
- data/previews/primer/open_project/tree_view_preview/loading_failure.html.erb +36 -0
- data/previews/primer/open_project/tree_view_preview/loading_skeleton.html.erb +12 -0
- data/previews/primer/open_project/tree_view_preview/loading_spinner.html.erb +12 -0
- data/previews/primer/open_project/tree_view_preview/playground.html.erb +4 -0
- data/previews/primer/open_project/tree_view_preview.rb +139 -0
- data/static/arguments.json +512 -0
- data/static/audited_at.json +21 -0
- data/static/classes.json +18 -0
- data/static/constants.json +108 -1
- data/static/info_arch.json +1612 -0
- data/static/previews.json +180 -0
- data/static/statuses.json +21 -0
- metadata +79 -2
@@ -1 +1 @@
|
|
1
|
-
.SelectPanel-
|
1
|
+
.SelectPanel-loadingPanel{min-height:min(calc(var(--overlay-height) - 10rem),calc(100vh - 2rem))}.SelectPanel-emptyPanel{align-items:center;display:flex;justify-content:center;min-height:min(calc(var(--overlay-height) - 23rem),calc(100vh - 2rem))}
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"sources":["select_panel.pcss"],"names":[],"mappings":"
|
1
|
+
{"version":3,"sources":["select_panel.pcss"],"names":[],"mappings":"AAAA,0BACE,sEACF,CAEA,wBAEE,kBAAmB,CACnB,YAAa,CACb,sBAAuB,CAHvB,sEAIF","file":"select_panel.css","sourcesContent":[".SelectPanel-loadingPanel {\n min-height: min(calc(var(--overlay-height) - 10rem), calc(100vh - 2rem));\n}\n\n.SelectPanel-emptyPanel {\n min-height: min(calc(var(--overlay-height) - 23rem), calc(100vh - 2rem));\n align-items: center;\n display: flex;\n justify-content: center;\n}\n"]}
|
@@ -97,7 +97,7 @@
|
|
97
97
|
<%= render(@list) %>
|
98
98
|
<% end %>
|
99
99
|
</div>
|
100
|
-
<div data-target="select-panel.noResults" class="
|
100
|
+
<div data-target="select-panel.noResults" class="SelectPanel-emptyPanel" hidden>
|
101
101
|
<h2 class="v-align-middle m-3 f5"><%= @no_results_label %></h2>
|
102
102
|
</div>
|
103
103
|
<% end %>
|
@@ -1,7 +1,10 @@
|
|
1
1
|
.SelectPanel-loadingPanel {
|
2
|
-
min-height: min(var(--overlay-height) - 10rem, 100vh - 2rem);
|
2
|
+
min-height: min(calc(var(--overlay-height) - 10rem), calc(100vh - 2rem));
|
3
3
|
}
|
4
4
|
|
5
5
|
.SelectPanel-emptyPanel {
|
6
|
-
min-height: min(var(--overlay-height) -
|
6
|
+
min-height: min(calc(var(--overlay-height) - 23rem), calc(100vh - 2rem));
|
7
|
+
align-items: center;
|
8
|
+
display: flex;
|
9
|
+
justify-content: center;
|
7
10
|
}
|
@@ -1,4 +1,4 @@
|
|
1
|
-
<%= render(Primer::BaseComponent.new(tag: :span, hidden: @hidden, data: { target: @target })) do %>
|
1
|
+
<%= render(Primer::BaseComponent.new(tag: :span, hidden: @hidden, data: { target: @target }, **@wrapper_arguments)) do %>
|
2
2
|
<%= render Primer::BaseComponent.new(**@system_arguments) do %>
|
3
3
|
<circle cx="8" cy="8" r="7" stroke="currentColor" stroke-opacity="0.25" stroke-width="2" vector-effect="non-scaling-stroke" fill="none" />
|
4
4
|
<path d="M15 8a7.002 7.002 0 00-7-7" stroke="currentColor" stroke-width="2" stroke-linecap="round" vector-effect="non-scaling-stroke" />
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Primer
|
4
|
+
module OpenProject
|
5
|
+
class FileTreeView
|
6
|
+
class DirectoryNode < TreeView::SubTreeNode
|
7
|
+
def initialize(icon_arguments: nil, expanded_icon_arguments: nil, collapsed_icon_arguments: nil, **system_arguments)
|
8
|
+
@expanded_icon_arguments = expanded_icon_arguments || icon_arguments || {}
|
9
|
+
@collapsed_icon_arguments = collapsed_icon_arguments || icon_arguments || {}
|
10
|
+
|
11
|
+
super(**system_arguments)
|
12
|
+
end
|
13
|
+
|
14
|
+
def with_file(**system_arguments, &block)
|
15
|
+
with_leaf(**system_arguments, component_klass: FileNode, &block)
|
16
|
+
end
|
17
|
+
|
18
|
+
def with_directory(**system_arguments, &block)
|
19
|
+
with_sub_tree(**system_arguments, component_klass: DirectoryNode, &block)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Primer
|
4
|
+
module OpenProject
|
5
|
+
class FileTreeView
|
6
|
+
class FileNode < TreeView::LeafNode
|
7
|
+
def initialize(icon_arguments: {}, **system_arguments)
|
8
|
+
@icon_arguments = icon_arguments
|
9
|
+
super(**system_arguments)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Primer
|
4
|
+
module OpenProject
|
5
|
+
class FileTreeView < TreeView
|
6
|
+
def with_file(**system_arguments, &block)
|
7
|
+
with_leaf(**system_arguments, component_klass: FileNode, &block)
|
8
|
+
end
|
9
|
+
|
10
|
+
def with_directory(**system_arguments, &block)
|
11
|
+
with_sub_tree(**system_arguments, component_klass: DirectoryNode, &block)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -150,7 +150,7 @@ module Primer
|
|
150
150
|
@mobile_segmented_control = Primer::Alpha::SegmentedControl.new(**system_arguments,
|
151
151
|
**mobile_args,
|
152
152
|
mr: 2,
|
153
|
-
display:
|
153
|
+
display: MOBILE_ACTIONS_DISPLAY)
|
154
154
|
@mobile_segmented_control_block = block
|
155
155
|
|
156
156
|
Primer::Alpha::SegmentedControl.new(**system_arguments)
|
@@ -0,0 +1 @@
|
|
1
|
+
@keyframes shimmer{0%{mask-position:200%}to{mask-position:0}}.SkeletonBox{animation:shimmer;background-color:var(--bgColor-muted);border-radius:var(--borderRadius-small);display:block;height:1rem}@media (prefers-reduced-motion:no-preference){.SkeletonBox{animation:shimmer;animation-duration:1s;animation-iteration-count:infinite;mask-image:linear-gradient(75deg,#000 30%,#000000a6 80%);mask-size:200%}}@media (forced-colors:active){.SkeletonBox{outline:1px solid #0000;outline-offset:-1px}}
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"sources":["skeleton_box.pcss"],"names":[],"mappings":"AAAA,mBACE,GACE,kBACF,CAEA,GACE,eACF,CACF,CAEA,aAKE,iBAAkB,CAFlB,qCAAsC,CACtC,uCAAwC,CAHxC,aAAc,CACd,WAiBF,CAZE,8CAPF,aAUI,iBAAkB,CAClB,qBAAsB,CACtB,kCAAmC,CAJnC,wDAAqE,CACrE,cAUJ,CANE,CAEA,8BAfF,aAgBI,uBAA8B,CAC9B,mBAEJ,CADE","file":"skeleton_box.css","sourcesContent":["@keyframes shimmer {\n from {\n mask-position: 200%;\n }\n\n to {\n mask-position: 0%;\n }\n}\n\n.SkeletonBox {\n display: block;\n height: 1rem;\n background-color: var(--bgColor-muted);\n border-radius: var(--borderRadius-small);\n animation: shimmer;\n\n @media (prefers-reduced-motion: no-preference) {\n mask-image: linear-gradient(75deg, #000 30%, rgba(0, 0, 0, 0.65) 80%);\n mask-size: 200%;\n animation: shimmer;\n animation-duration: 1s;\n animation-iteration-count: infinite;\n }\n\n @media (forced-colors: active) {\n outline: 1px solid transparent;\n outline-offset: -1px;\n }\n}\n"]}
|
@@ -0,0 +1 @@
|
|
1
|
+
<%= render(Primer::BaseComponent.new(**@system_arguments)) %>
|
@@ -0,0 +1,30 @@
|
|
1
|
+
@keyframes shimmer {
|
2
|
+
from {
|
3
|
+
mask-position: 200%;
|
4
|
+
}
|
5
|
+
|
6
|
+
to {
|
7
|
+
mask-position: 0%;
|
8
|
+
}
|
9
|
+
}
|
10
|
+
|
11
|
+
.SkeletonBox {
|
12
|
+
display: block;
|
13
|
+
height: 1rem;
|
14
|
+
background-color: var(--bgColor-muted);
|
15
|
+
border-radius: var(--borderRadius-small);
|
16
|
+
animation: shimmer;
|
17
|
+
|
18
|
+
@media (prefers-reduced-motion: no-preference) {
|
19
|
+
mask-image: linear-gradient(75deg, #000 30%, rgba(0, 0, 0, 0.65) 80%);
|
20
|
+
mask-size: 200%;
|
21
|
+
animation: shimmer;
|
22
|
+
animation-duration: 1s;
|
23
|
+
animation-iteration-count: infinite;
|
24
|
+
}
|
25
|
+
|
26
|
+
@media (forced-colors: active) {
|
27
|
+
outline: 1px solid transparent;
|
28
|
+
outline-offset: -1px;
|
29
|
+
}
|
30
|
+
}
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Primer
|
4
|
+
module OpenProject
|
5
|
+
# A SkeletonBox provides a placeholder for non-text, non-Avatar elements (e.g., hero images)
|
6
|
+
# that are still loading. You can adjust width and height to match the content's dimensions.
|
7
|
+
class SkeletonBox < Primer::Component
|
8
|
+
# @param height [String] Any valid CSS height.
|
9
|
+
# @param width [String] Any valid CSS width.
|
10
|
+
# @param system_arguments [Hash] <%= link_to_system_arguments_docs %>
|
11
|
+
def initialize(height: nil, width: nil, **system_arguments)
|
12
|
+
@system_arguments = deny_tag_argument(**system_arguments)
|
13
|
+
|
14
|
+
styles = []
|
15
|
+
styles << "width: #{width}" if width
|
16
|
+
styles << "height: #{height}" if height
|
17
|
+
|
18
|
+
@system_arguments[:tag] = :div
|
19
|
+
@system_arguments[:style] = styles.join("; ") if styles.present?
|
20
|
+
@system_arguments[:classes] = class_names(
|
21
|
+
@system_arguments.delete(:classes),
|
22
|
+
"SkeletonBox"
|
23
|
+
)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Primer
|
4
|
+
module OpenProject
|
5
|
+
# A Helper class to create a Button with required icon inside the SubHeader action slot
|
6
|
+
# Do not use standalone
|
7
|
+
class SubHeader::Button < Primer::Component
|
8
|
+
status :open_project
|
9
|
+
|
10
|
+
renders_one :leading_visual_icon, lambda { |**system_arguments|
|
11
|
+
# Do nothing as this slot is reserved for the enforced leading icon
|
12
|
+
}
|
13
|
+
|
14
|
+
# @param icon [Symbol] The name of an <%= link_to_octicons %> icon to use as leading visual
|
15
|
+
# @param system_arguments [Hash] <%= link_to_system_arguments_docs %>
|
16
|
+
def initialize(icon:, **system_arguments)
|
17
|
+
@icon = icon
|
18
|
+
@button = Primer::Beta::Button.new(**system_arguments)
|
19
|
+
end
|
20
|
+
|
21
|
+
delegate :trailing_visual_icon?, :trailing_visual_icon, :with_trailing_visual_icon, :with_trailing_visual_content_icon,
|
22
|
+
:trailing_visual_counter?, :trailing_visual_counter, :with_trailing_visual_counter, :with_trailing_visual_content_counter,
|
23
|
+
:trailing_visual_label?, :trailing_visual_label, :with_trailing_visual_label, :with_trailing_visual_content_label,
|
24
|
+
:trailing_action?, :trailing_action, :with_trailing_action, :with_trailing_action_content,
|
25
|
+
:tooltip?, :tooltip, :with_tooltip, :with_tooltip,
|
26
|
+
to: :@button
|
27
|
+
|
28
|
+
def before_render
|
29
|
+
if leading_visual_icon.present?
|
30
|
+
raise ArgumentError,
|
31
|
+
"Do not use the leading_visual_icon slot within the SubHeader, as it is reserved. Instead provide a leading_icon within the subHeader button slot"
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def call
|
36
|
+
render(@button) do |button|
|
37
|
+
button.with_leading_visual_icon(icon: @icon)
|
38
|
+
content
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Primer
|
4
|
+
module OpenProject
|
5
|
+
# A Helper class to create ButtonGroups inside the SubHeader action slot
|
6
|
+
# Do not use standalone
|
7
|
+
class SubHeader::ButtonGroup < Primer::Beta::ButtonGroup
|
8
|
+
status :open_project
|
9
|
+
|
10
|
+
def with_button(icon:, **system_arguments, &block)
|
11
|
+
system_arguments[:icon] = icon
|
12
|
+
super(component_klass: Primer::OpenProject::SubHeader::ButtonGroup, **system_arguments, &block)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Primer
|
4
|
+
module OpenProject
|
5
|
+
# A Helper class to create an ActionMenu with a required icon on the trigger button.
|
6
|
+
# It is meant to be used inside the SubHeader
|
7
|
+
# Do not use standalone
|
8
|
+
class SubHeader::Menu < Primer::Component
|
9
|
+
status :open_project
|
10
|
+
|
11
|
+
renders_one :show_button, lambda { |**system_arguments|
|
12
|
+
# Do nothing as this slot is reserved for the enforced leading icon
|
13
|
+
}
|
14
|
+
|
15
|
+
def set_show_button(**system_arguments)
|
16
|
+
aria_label = aria("label", system_arguments) || @label
|
17
|
+
|
18
|
+
if @icon_only
|
19
|
+
@menu.with_show_button(icon: @leading_icon, "aria-label": aria_label, **system_arguments)
|
20
|
+
else
|
21
|
+
@menu.with_show_button("aria-label": aria_label, **system_arguments) do |button|
|
22
|
+
button.with_leading_visual_icon(icon: @leading_icon)
|
23
|
+
button.with_trailing_action_icon(icon: @trailing_icon) unless @trailing_icon.nil?
|
24
|
+
@label
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
# @param icon_only [Boolean] Whether the trigger button is an IconButton
|
30
|
+
# @param leading_icon [Symbol] Name of Octicon icon to use as either leading icon or IconButton.
|
31
|
+
# @param label [String] The button label
|
32
|
+
# @param button_arguments [Hash] Additional arguments for the button
|
33
|
+
# @param system_arguments [Hash] <%= link_to_system_arguments_docs %>
|
34
|
+
def initialize(icon_only: false, leading_icon:, label:, trailing_icon: nil, button_arguments: {}, **system_arguments)
|
35
|
+
@icon_only = icon_only
|
36
|
+
@leading_icon = leading_icon
|
37
|
+
@trailing_icon = trailing_icon
|
38
|
+
@label = label
|
39
|
+
|
40
|
+
if @label.nil? || @label.empty?
|
41
|
+
raise ArgumentError, "You need to provide a valid label."
|
42
|
+
end
|
43
|
+
|
44
|
+
@button_arguments = button_arguments
|
45
|
+
|
46
|
+
@menu = Primer::Alpha::ActionMenu.new(**system_arguments)
|
47
|
+
end
|
48
|
+
|
49
|
+
delegate :with_item, :with_divider, :with_avatar_item, :with_group,
|
50
|
+
to: :@menu
|
51
|
+
|
52
|
+
def before_render
|
53
|
+
if show_button
|
54
|
+
raise ArgumentError,
|
55
|
+
"Do not use the show_button slot within the SubHeader, as it is reserved. Instead provide a leading_icon within the subHeader button slot"
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def call
|
60
|
+
render(@menu) do
|
61
|
+
set_show_button(**@button_arguments)
|
62
|
+
content
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Primer
|
4
|
+
module OpenProject
|
5
|
+
# A Helper class to create SegmentedControls inside the SubHeader action slot
|
6
|
+
# Do not use standalone
|
7
|
+
class SubHeader::SegmentedControl < Primer::Alpha::SegmentedControl
|
8
|
+
status :open_project
|
9
|
+
|
10
|
+
def with_item(icon:, **system_arguments, &block)
|
11
|
+
system_arguments[:icon] = icon
|
12
|
+
super(component_klass: Primer::OpenProject::SubHeader::SegmentedControl, **system_arguments, &block)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -1 +1 @@
|
|
1
|
-
.SubHeader{align-items:center;display:grid;grid-template-areas:"left middle right" "bottom bottom bottom";grid-template-columns:auto 1fr auto;margin-bottom:
|
1
|
+
.SubHeader{align-items:center;display:grid;grid-template-areas:"left middle right" "bottom bottom bottom";grid-template-columns:auto 1fr auto;margin-bottom:var(--base-size-16)}.SubHeader--expandedSearch{grid-template-areas:"left left left" "bottom bottom bottom"}.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;grid-area:left;width:100%}:is(.SubHeader-leftPane [class*=FormControl-input-width--]):not(.FormControl-input-width--auto){width:100vw}.SubHeader-filterContainer{display:flex;flex-basis:max-content;gap:8px;width:100%}.SubHeader-filterInput_hiddenClearButton+.FormControl-input-trailingAction{display:none}@media (max-width:543.98px){.SubHeader{grid-template-areas:"left right" "middle middle" "bottom bottom";grid-template-columns:1fr auto}.SubHeader--emptyLeftPane{grid-template-areas:"middle middle right" "bottom bottom bottom";grid-template-columns:auto 1fr auto}.SubHeader--emptyLeftPane .SubHeader-middlePane{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.SubHeader-middlePane{text-align:left}.SubHeader-middlePane:has(>*){margin-top:var(--stack-gap-normal)}}
|
@@ -9,6 +9,9 @@
|
|
9
9
|
".SubHeader-leftPane",
|
10
10
|
":is(.SubHeader-leftPane [class*=FormControl-input-width--]):not(.FormControl-input-width--auto)",
|
11
11
|
".SubHeader-filterContainer",
|
12
|
-
".SubHeader-filterInput_hiddenClearButton
|
12
|
+
".SubHeader-filterInput_hiddenClearButton+.FormControl-input-trailingAction",
|
13
|
+
".SubHeader--emptyLeftPane",
|
14
|
+
".SubHeader--emptyLeftPane .SubHeader-middlePane",
|
15
|
+
".SubHeader-middlePane:has(>*)"
|
13
16
|
]
|
14
17
|
}
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"sources":["sub_header.pcss"],"names":[],"mappings":"AAEA,WAII,kBAAmB,CAHnB,YAAa,CACb,8DAA+D,CAC/D,mCAAoC,CAEpC,
|
1
|
+
{"version":3,"sources":["sub_header.pcss"],"names":[],"mappings":"AAEA,WAII,kBAAmB,CAHnB,YAAa,CACb,8DAA+D,CAC/D,mCAAoC,CAEpC,iCACJ,CAEA,2BACI,2DACJ,CAEA,qBAGI,kBAAmB,CACnB,eAAgB,CAFhB,YAAa,CADb,eAIJ,CAEA,sBACI,gBAAiB,CACjB,iBACJ,CAEA,sBACI,gBACJ,CAEA,oBAGI,kBAAmB,CADnB,YAAa,CADb,cAAe,CAGf,UASJ,CAJQ,gGACI,WACJ,CAIR,2BACI,YAAa,CACb,sBAAuB,CAEvB,OAAQ,CADR,UAEJ,CAEA,2EACE,YACF,CAEA,4BACI,WACI,gEAAiE,CACjE,8BACJ,CAEA,0BACI,gEAAiE,CACjE,mCACJ,CAEA,gDAGI,eAAgB,CADhB,sBAAuB,CADvB,kBAGJ,CAEA,sBACI,eACJ,CAEA,8BACI,kCACJ,CACJ","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: var(--base-size-16);\n}\n\n.SubHeader--expandedSearch {\n grid-template-areas: \"left left left\" \"bottom bottom bottom\";\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\n /* Since the container is not full width (due to the grid around it)\n we want it to grow, and then be limited by the max-width of the \"FormControl-input-width--xy\" class */\n & [class*='FormControl-input-width--'] {\n &:not(.FormControl-input-width--auto) {\n width: 100vw;\n }\n }\n}\n\n.SubHeader-filterContainer {\n display: flex;\n flex-basis: max-content;\n width: 100%;\n gap: 8px;\n}\n\n.SubHeader-filterInput_hiddenClearButton + .FormControl-input-trailingAction {\n display: none;\n}\n\n@media (max-width: 543.98px) {\n .SubHeader {\n grid-template-areas: \"left right\" \"middle middle\" \"bottom bottom\";\n grid-template-columns: 1fr auto;\n }\n\n .SubHeader--emptyLeftPane {\n grid-template-areas: \"middle middle right\" \"bottom bottom bottom\";\n grid-template-columns: auto 1fr auto;\n }\n\n .SubHeader--emptyLeftPane .SubHeader-middlePane {\n white-space: nowrap;\n text-overflow: ellipsis;\n overflow: hidden;\n }\n\n .SubHeader-middlePane {\n text-align: left;\n }\n\n .SubHeader-middlePane:has(> *) {\n margin-top: var(--stack-gap-normal);\n }\n}\n"]}
|
@@ -6,17 +6,38 @@
|
|
6
6
|
I18n.t("button_cancel")
|
7
7
|
end if @mobile_filter_cancel.present? %>
|
8
8
|
<% end if filter_input.present? %>
|
9
|
+
|
9
10
|
<%= render @mobile_filter_trigger if @mobile_filter_trigger.present? %>
|
11
|
+
|
12
|
+
<%= render(@mobile_filter_button) if @mobile_filter_button.present? %>
|
13
|
+
|
10
14
|
<%= filter_button %>
|
15
|
+
|
16
|
+
<%= segmented_control %>
|
17
|
+
|
18
|
+
<% if @segmented_control_block.present? %>
|
19
|
+
<%= render(@mobile_segmented_control) do |control| %>
|
20
|
+
<% @segmented_control_block.call(control) %>
|
21
|
+
<% end %>
|
22
|
+
<% end %>
|
11
23
|
</div>
|
24
|
+
|
12
25
|
<div class="SubHeader-middlePane" data-targets="<%= HIDDEN_FILTER_TARGET_SELECTOR %>">
|
13
26
|
<%= text %>
|
14
27
|
</div>
|
28
|
+
|
15
29
|
<div class="SubHeader-rightPane" data-targets="<%= HIDDEN_FILTER_TARGET_SELECTOR %>">
|
16
30
|
<% actions.each do |action| %>
|
17
31
|
<%= action %>
|
18
32
|
<% end %>
|
33
|
+
|
34
|
+
<% @mobile_actions.each do |mobile_action| %>
|
35
|
+
<%= render(mobile_action[:component]) do |action| %>
|
36
|
+
<% mobile_action[:block].call(action) %>
|
37
|
+
<% end %>
|
38
|
+
<% end unless @mobile_actions.nil? %>
|
19
39
|
</div>
|
40
|
+
|
20
41
|
<% if bottom_pane_component.present? %>
|
21
42
|
<div class="SubHeader-bottomPane">
|
22
43
|
<%= bottom_pane_component %>
|
@@ -5,7 +5,7 @@
|
|
5
5
|
grid-template-areas: "left middle right" "bottom bottom bottom";
|
6
6
|
grid-template-columns: auto 1fr auto;
|
7
7
|
align-items: center;
|
8
|
-
margin-bottom:
|
8
|
+
margin-bottom: var(--base-size-16);
|
9
9
|
}
|
10
10
|
|
11
11
|
.SubHeader--expandedSearch {
|
@@ -33,7 +33,6 @@
|
|
33
33
|
display: flex;
|
34
34
|
align-items: center;
|
35
35
|
width: 100%;
|
36
|
-
gap: 12px;
|
37
36
|
|
38
37
|
/* Since the container is not full width (due to the grid around it)
|
39
38
|
we want it to grow, and then be limited by the max-width of the "FormControl-input-width--xy" class */
|
@@ -46,10 +45,37 @@
|
|
46
45
|
|
47
46
|
.SubHeader-filterContainer {
|
48
47
|
display: flex;
|
48
|
+
flex-basis: max-content;
|
49
49
|
width: 100%;
|
50
50
|
gap: 8px;
|
51
51
|
}
|
52
52
|
|
53
|
-
.SubHeader-filterInput_hiddenClearButton +
|
53
|
+
.SubHeader-filterInput_hiddenClearButton + .FormControl-input-trailingAction {
|
54
54
|
display: none;
|
55
55
|
}
|
56
|
+
|
57
|
+
@media (max-width: 543.98px) {
|
58
|
+
.SubHeader {
|
59
|
+
grid-template-areas: "left right" "middle middle" "bottom bottom";
|
60
|
+
grid-template-columns: 1fr auto;
|
61
|
+
}
|
62
|
+
|
63
|
+
.SubHeader--emptyLeftPane {
|
64
|
+
grid-template-areas: "middle middle right" "bottom bottom bottom";
|
65
|
+
grid-template-columns: auto 1fr auto;
|
66
|
+
}
|
67
|
+
|
68
|
+
.SubHeader--emptyLeftPane .SubHeader-middlePane {
|
69
|
+
white-space: nowrap;
|
70
|
+
text-overflow: ellipsis;
|
71
|
+
overflow: hidden;
|
72
|
+
}
|
73
|
+
|
74
|
+
.SubHeader-middlePane {
|
75
|
+
text-align: left;
|
76
|
+
}
|
77
|
+
|
78
|
+
.SubHeader-middlePane:has(> *) {
|
79
|
+
margin-top: var(--stack-gap-normal);
|
80
|
+
}
|
81
|
+
}
|