-
Notifications
You must be signed in to change notification settings - Fork 3.4k
Expand file tree
/
Copy pathsub-header.md.erb
More file actions
178 lines (128 loc) · 7.19 KB
/
Copy pathsub-header.md.erb
File metadata and controls
178 lines (128 loc) · 7.19 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
This component is an own implementation for OpenProject requirements of contextual elements that affect the content of the page below. Such a component does not exist in the Primer Design System.
## Overview
<%= embed OpenProject::Common::SubHeaderPreview, :default %>
## Anatomy
### Desktop
The SubHeader accepts a number of additional components. **All buttons** within the SubHeader require an icon to be shown, either as leading icon or as an icon-only variant.
On the left side:
- **Search filter**: (Optional) A basic [text input](https://primer.style/components/text-input) with a [search icon](https://primer.style/components/text-input#with-leading-and-trailing-visuals) which is mostly used on index pages to filter the elements below. Per default, the search input is collapsed to an icon button and changes on click to a text input. To avoid this, use `collapsed_search: false`.
- **Sort action** (Optional) A generic slot for a sort button component. It is recommended to use IconButtons here.
- **Group action** (Optional) A generic slot for a group button component. It is recommended to use IconButtons here.
- **Quick filters** (Optional) Up to 5 QuickFilter can be rendered here. When using more then one quick filter, an `All Filter` button is required.
- **All Filter button:** (Optional) A button which is shown next to the filter input (or on the very left, if there is no filter input)
At the center of the SubHeader:
- **Text:** (Optional) A bold text shown in the middle of the SubHeader
On the right side:
- **Action buttons**: (Optional) A set of buttons, e.g.
- **A primary button**: (Optional) This is often an *add* action
- **Secondary buttons**: (Optional) Additional action can be offered to the user.
- **An icon-only ButtonGroup**: (Optional) Rarer but additional actions can be grouped to show their connection.
### Mobile
The SubHeader automatically adapts to mobile screens:
- All actions on both sides (including Buttons, SegmentedControls, ButtonGroups, etc) always turn into icon only variants without labels.
- There is a search IconButton; on click, it reveals the search input takes the full length (hiding all other actions), with a cancel button to go back to the previous state
- When using more than one QuickFilter, they are hidden on mobile. The "All filters" button remains visible to preserve functionality.
## Best practices
**Do**
- Restrict SubHeader actions to the page's content-specific actions (e.g. filtering or creating a new object).
- Use IconButtons instead of Buttons for actions only when the icon is clear enough to describe the action.
- When more actions are necessary, or if a menu is needed, use an ActionMenu instead of the ActionButtons.
- Use IconButtons for the sort and group components.
- Use `collapsed_search: false` when the left side only shows the search input and no further filter actions.
**Don't**
- Use the SubHeader to perform generic view actions (should be part of the PageHeader)
## Used in
* Project list
* Members
* Meetings
* Storages
* ...
## Examples
For detailed examples have a look at the other [preview examples](../../inspect/primer/open_project/sub_header/playground) of the component.
This is an exemplary playground of the `Primer::OpenProject::SubHeader`.
<%= embed OpenProject::Common::SubHeaderPreview, :playground, panels: %i[params source] %>
## Technical notes
### Buttons
In order to enforce the icons to be visible we introduced an extra argument for each slot called `leading_visual` which you have to pass. As a consequence you cannot call the default Button slot `with_leading_visual_icon` any more. We do that internally with the provided `leading_visual`.
The filter button is an exception to this as we already provide the `filter` icon per default.
```rb
render(Primer::OpenProject::SubHeader.new) do |component|
component.with_action_button(leading_icon: :plus, label: "Create", scheme: :primary) do
"Create"
end
end
```
If you need an icon-only Button, you can pass an addition argument called `icon_only: true`
```rb
render(Primer::OpenProject::SubHeader.new) do |component|
component.with_action_button(icon_only: true, leading_icon: :plus, label: "Create", scheme: :primary)
end
```
### ActionMenu
The syntax for an `ActionMenu` within the SubHeader is a bit special due to the constraint of enforcing the icon. Here as well, you cannot use the `with_show_button` slot but rather pass the arguments when calling a dedicated slot:
```html
<%=
render(Primer::OpenProject::SubHeader.new) do |component|
component.with_action_menu(leading_icon: :plus, label: "Create", button_arguments: { scheme: :primary, "aria-label": "Menu" }) do |menu|
menu.with_item(label: "Subitem 1") do |item|
item.with_leading_visual_icon(icon: :paste)
end
menu.with_item(label: "Subitem 2") do |item|
item.with_leading_visual_icon(icon: :log)
end
end
end
%>
```
### Dialogs
We currently only allow async dialogs to be rendered from the SubHeader. So you can render a normal action button that directs to an endpoint which returns the async dialog. For more details on how async dialogs work, please have a look [here](../patterns/dialogs).
```html
<%=
render(Primer::OpenProject::SubHeader.new) do |component|
component.with_action_button(leading_icon: :alert,
label: "Open Dialog",
tag: :a,
href: "show_dialog_path",
data: { controller: "async-dialog" }) do
"Open Dialog"
end
end
%>
```
### Sorting and grouping
The sort and group actions are always displayed after the search but before the quick filters.
```html
<%=
render(Primer::OpenProject::SubHeader.new) do |component|
component.with_quick_sort do
render(Foo::BarSortComponent.new(..))
end
component.with_quick_group do
render(Foo::BarGroupComponent.new(..))
end
end
%>
```
### QuickFilters
The `with_quick_filter` slot only offers a generic slot for a quick filter taking care of placement, responsiveness and mobile behaviour. The logic is part of the actual [QuickFilter components](../patterns/quick_filters).
```html
<%=
render(Primer::OpenProject::SubHeader.new) do |component|
component.with_quick_filter do
render(Foo::BarFilterComponent.new(query: @query, project: @project))
end
component.with_quick_filter do
render(Foo::OtherFilterComponent.new(query: @query, project: @project))
end
# The all filters button is required when using more than one quick filter
component.with_filter_component(mobile_label: "All filters") do
render(Foo::AllFilterComponent.new(query: @query, project: @project))
end
end
%>
```
### All filters button
The "All filters" button is required when using more than one quick filter. It can be rendered either via the `with_filter_button` slot or as a component via `with_filter_component`. When using the latter, you have to manually make sure that the button fulfills the following requirements:
* Use `invisible` scheme
* Use `icon: :filter`
* Use `label: "All filters"`