openproject-primer_view_components 0.13.0 → 0.14.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 +22 -0
- data/app/assets/javascripts/app/components/primer/primer.d.ts +0 -1
- 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/action_bar_element.js +2 -0
- data/app/components/primer/alpha/action_bar_element.ts +2 -0
- data/app/components/primer/alpha/action_menu/action_menu_element.js +20 -3
- data/app/components/primer/alpha/action_menu/action_menu_element.ts +27 -1
- data/app/components/primer/alpha/overlay.css +1 -1
- data/app/components/primer/alpha/overlay.css.json +0 -1
- data/app/components/primer/alpha/overlay.css.map +1 -1
- data/app/components/primer/alpha/overlay.pcss +0 -12
- data/app/components/primer/alpha/tool_tip.js +76 -3
- data/app/components/primer/alpha/tool_tip.ts +76 -3
- data/app/components/primer/open_project/page_header.css +1 -1
- data/app/components/primer/open_project/page_header.css.json +4 -1
- data/app/components/primer/open_project/page_header.css.map +1 -1
- data/app/components/primer/open_project/page_header.html.erb +6 -2
- data/app/components/primer/open_project/page_header.pcss +19 -6
- data/app/components/primer/open_project/page_header.rb +70 -0
- data/app/components/primer/primer.d.ts +0 -1
- data/app/components/primer/primer.js +0 -1
- data/app/components/primer/primer.pcss +0 -2
- data/app/components/primer/primer.ts +0 -1
- data/lib/primer/accessibility.rb +1 -3
- data/lib/primer/static/generate_info_arch.rb +6 -1
- data/lib/primer/view_components/version.rb +1 -1
- data/previews/primer/alpha/check_box_preview.rb +0 -3
- data/previews/primer/alpha/dialog_preview/with_text_input.html.erb +2 -1
- data/previews/primer/alpha/radio_button_preview.rb +0 -3
- data/previews/primer/open_project/page_header_preview.rb +39 -1
- data/static/classes.json +9 -0
- data/static/constants.json +12 -0
- data/static/info_arch.json +243 -8
- data/static/previews.json +198 -0
- metadata +2 -2
@@ -101,6 +101,8 @@ let ActionBarElement = class ActionBarElement extends HTMLElement {
|
|
101
101
|
};
|
102
102
|
_ActionBarElement_initialBarWidth = new WeakMap(), _ActionBarElement_previousBarWidth = new WeakMap(), _ActionBarElement_focusZoneAbortController = new WeakMap(), _ActionBarElement_instances = new WeakSet(), _ActionBarElement_isVisible = function _ActionBarElement_isVisible(element) {
|
103
103
|
// Safari doesn't support `checkVisibility` yet.
|
104
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
105
|
+
// @ts-ignore
|
104
106
|
if (typeof element.checkVisibility === 'function')
|
105
107
|
return element.checkVisibility();
|
106
108
|
return Boolean(element.offsetParent || element.offsetWidth || element.offsetHeight);
|
@@ -93,6 +93,8 @@ class ActionBarElement extends HTMLElement {
|
|
93
93
|
|
94
94
|
#isVisible(element: HTMLElement): boolean {
|
95
95
|
// Safari doesn't support `checkVisibility` yet.
|
96
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
97
|
+
// @ts-ignore
|
96
98
|
if (typeof element.checkVisibility === 'function') return element.checkVisibility()
|
97
99
|
|
98
100
|
return Boolean(element.offsetParent || element.offsetWidth || element.offsetHeight)
|
@@ -15,7 +15,7 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
|
|
15
15
|
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
16
16
|
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
17
17
|
};
|
18
|
-
var _ActionMenuElement_instances, _ActionMenuElement_abortController, _ActionMenuElement_originalLabel, _ActionMenuElement_inputName, _ActionMenuElement_invokerBeingClicked, _ActionMenuElement_softDisableItems, _ActionMenuElement_potentiallyDisallowActivation, _ActionMenuElement_isKeyboardActivation, _ActionMenuElement_isMouseActivation, _ActionMenuElement_isActivation, _ActionMenuElement_handleInvokerActivated, _ActionMenuElement_handleDialogItemActivated, _ActionMenuElement_handleItemActivated, _ActionMenuElement_activateItem, _ActionMenuElement_handleIncludeFragmentReplaced, _ActionMenuElement_handleFocusOut, _ActionMenuElement_show, _ActionMenuElement_hide, _ActionMenuElement_isOpen, _ActionMenuElement_setDynamicLabel, _ActionMenuElement_updateInput, _ActionMenuElement_firstItem_get, _ActionMenuElement_items_get;
|
18
|
+
var _ActionMenuElement_instances, _ActionMenuElement_abortController, _ActionMenuElement_originalLabel, _ActionMenuElement_inputName, _ActionMenuElement_invokerBeingClicked, _ActionMenuElement_softDisableItems, _ActionMenuElement_potentiallyDisallowActivation, _ActionMenuElement_isKeyboardActivation, _ActionMenuElement_isKeyboardActivationViaEnter, _ActionMenuElement_isKeyboardActivationViaSpace, _ActionMenuElement_isMouseActivation, _ActionMenuElement_isActivation, _ActionMenuElement_handleInvokerActivated, _ActionMenuElement_handleDialogItemActivated, _ActionMenuElement_handleItemActivated, _ActionMenuElement_activateItem, _ActionMenuElement_handleIncludeFragmentReplaced, _ActionMenuElement_handleFocusOut, _ActionMenuElement_show, _ActionMenuElement_hide, _ActionMenuElement_isOpen, _ActionMenuElement_setDynamicLabel, _ActionMenuElement_updateInput, _ActionMenuElement_firstItem_get, _ActionMenuElement_items_get;
|
19
19
|
import { controller, target } from '@github/catalyst';
|
20
20
|
import '@oddbird/popover-polyfill';
|
21
21
|
const validSelectors = ['[role="menuitem"]', '[role="menuitemcheckbox"]', '[role="menuitemradio"]'];
|
@@ -109,7 +109,7 @@ let ActionMenuElement = class ActionMenuElement extends HTMLElement {
|
|
109
109
|
__classPrivateFieldGet(this, _ActionMenuElement_abortController, "f").abort();
|
110
110
|
}
|
111
111
|
handleEvent(event) {
|
112
|
-
var _a;
|
112
|
+
var _a, _b;
|
113
113
|
const targetIsInvoker = (_a = this.invokerElement) === null || _a === void 0 ? void 0 : _a.contains(event.target);
|
114
114
|
const eventIsActivation = __classPrivateFieldGet(this, _ActionMenuElement_instances, "m", _ActionMenuElement_isActivation).call(this, event);
|
115
115
|
if (targetIsInvoker && event.type === 'mousedown') {
|
@@ -151,6 +151,16 @@ let ActionMenuElement = class ActionMenuElement extends HTMLElement {
|
|
151
151
|
}
|
152
152
|
__classPrivateFieldGet(this, _ActionMenuElement_instances, "m", _ActionMenuElement_activateItem).call(this, event, item);
|
153
153
|
__classPrivateFieldGet(this, _ActionMenuElement_instances, "m", _ActionMenuElement_handleItemActivated).call(this, event, item);
|
154
|
+
// Pressing the space key on a button or link will cause the page to scroll unless preventDefault()
|
155
|
+
// is called. While calling preventDefault() appears to have no effect on link navigation, it skips
|
156
|
+
// form submission. The code below therefore only calls preventDefault() if the button has been
|
157
|
+
// activated by the space key, and manually submits the form if the button is a submit button.
|
158
|
+
if (__classPrivateFieldGet(this, _ActionMenuElement_instances, "m", _ActionMenuElement_isKeyboardActivationViaSpace).call(this, event)) {
|
159
|
+
event.preventDefault();
|
160
|
+
if (item.getAttribute('type') === 'submit') {
|
161
|
+
(_b = item.closest('form')) === null || _b === void 0 ? void 0 : _b.submit();
|
162
|
+
}
|
163
|
+
}
|
154
164
|
return;
|
155
165
|
}
|
156
166
|
if (event.type === 'include-fragment-replaced') {
|
@@ -176,10 +186,17 @@ _ActionMenuElement_abortController = new WeakMap(), _ActionMenuElement_originalL
|
|
176
186
|
event.stopImmediatePropagation();
|
177
187
|
}
|
178
188
|
}, _ActionMenuElement_isKeyboardActivation = function _ActionMenuElement_isKeyboardActivation(event) {
|
189
|
+
return __classPrivateFieldGet(this, _ActionMenuElement_instances, "m", _ActionMenuElement_isKeyboardActivationViaEnter).call(this, event) || __classPrivateFieldGet(this, _ActionMenuElement_instances, "m", _ActionMenuElement_isKeyboardActivationViaSpace).call(this, event);
|
190
|
+
}, _ActionMenuElement_isKeyboardActivationViaEnter = function _ActionMenuElement_isKeyboardActivationViaEnter(event) {
|
191
|
+
return (event instanceof KeyboardEvent &&
|
192
|
+
event.type === 'keydown' &&
|
193
|
+
!(event.ctrlKey || event.altKey || event.metaKey || event.shiftKey) &&
|
194
|
+
event.key === 'Enter');
|
195
|
+
}, _ActionMenuElement_isKeyboardActivationViaSpace = function _ActionMenuElement_isKeyboardActivationViaSpace(event) {
|
179
196
|
return (event instanceof KeyboardEvent &&
|
180
197
|
event.type === 'keydown' &&
|
181
198
|
!(event.ctrlKey || event.altKey || event.metaKey || event.shiftKey) &&
|
182
|
-
|
199
|
+
event.key === ' ');
|
183
200
|
}, _ActionMenuElement_isMouseActivation = function _ActionMenuElement_isMouseActivation(event) {
|
184
201
|
return event instanceof MouseEvent && event.type === 'click';
|
185
202
|
}, _ActionMenuElement_isActivation = function _ActionMenuElement_isActivation(event) {
|
@@ -134,11 +134,24 @@ export class ActionMenuElement extends HTMLElement {
|
|
134
134
|
}
|
135
135
|
|
136
136
|
#isKeyboardActivation(event: Event): boolean {
|
137
|
+
return this.#isKeyboardActivationViaEnter(event) || this.#isKeyboardActivationViaSpace(event)
|
138
|
+
}
|
139
|
+
|
140
|
+
#isKeyboardActivationViaEnter(event: Event): boolean {
|
141
|
+
return (
|
142
|
+
event instanceof KeyboardEvent &&
|
143
|
+
event.type === 'keydown' &&
|
144
|
+
!(event.ctrlKey || event.altKey || event.metaKey || event.shiftKey) &&
|
145
|
+
event.key === 'Enter'
|
146
|
+
)
|
147
|
+
}
|
148
|
+
|
149
|
+
#isKeyboardActivationViaSpace(event: Event): boolean {
|
137
150
|
return (
|
138
151
|
event instanceof KeyboardEvent &&
|
139
152
|
event.type === 'keydown' &&
|
140
153
|
!(event.ctrlKey || event.altKey || event.metaKey || event.shiftKey) &&
|
141
|
-
|
154
|
+
event.key === ' '
|
142
155
|
)
|
143
156
|
}
|
144
157
|
|
@@ -202,6 +215,19 @@ export class ActionMenuElement extends HTMLElement {
|
|
202
215
|
|
203
216
|
this.#activateItem(event, item)
|
204
217
|
this.#handleItemActivated(event, item)
|
218
|
+
|
219
|
+
// Pressing the space key on a button or link will cause the page to scroll unless preventDefault()
|
220
|
+
// is called. While calling preventDefault() appears to have no effect on link navigation, it skips
|
221
|
+
// form submission. The code below therefore only calls preventDefault() if the button has been
|
222
|
+
// activated by the space key, and manually submits the form if the button is a submit button.
|
223
|
+
if (this.#isKeyboardActivationViaSpace(event)) {
|
224
|
+
event.preventDefault()
|
225
|
+
|
226
|
+
if (item.getAttribute('type') === 'submit') {
|
227
|
+
item.closest('form')?.submit()
|
228
|
+
}
|
229
|
+
}
|
230
|
+
|
205
231
|
return
|
206
232
|
}
|
207
233
|
|
@@ -1 +1 @@
|
|
1
|
-
anchored-position[popover]{background:none;border-width:0;
|
1
|
+
anchored-position[popover]{background:none;border-width:0;min-width:192px;overflow:visible;padding:0;position:absolute}.Overlay{display:flex}anchored-position.not-anchored::-webkit-backdrop{background-color:var(--overlay-backdrop-bgColor,var(--color-neutral-muted))}anchored-position.not-anchored::backdrop{background-color:var(--overlay-backdrop-bgColor,var(--color-neutral-muted))}
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"sources":["overlay.pcss"],"names":[],"mappings":"AAAA,
|
1
|
+
{"version":3,"sources":["overlay.pcss"],"names":[],"mappings":"AAAA,2BAME,eAAgB,CALhB,cAAe,CAGf,eAAgB,CAChB,gBAAiB,CAHjB,SAAU,CACV,iBAIF,CAEA,SACE,YACF,CAEA,iDACE,2EACF,CAFA,yCACE,2EACF","file":"overlay.css","sourcesContent":["anchored-position[popover] {\n border-width: 0;\n padding: 0;\n position: absolute;\n min-width: 192px;\n overflow: visible;\n background: none;\n}\n\n.Overlay {\n display: flex;\n}\n\nanchored-position.not-anchored::backdrop {\n background-color: var(--overlay-backdrop-bgColor, var(--color-neutral-muted));\n}\n"]}
|
@@ -3,7 +3,6 @@ anchored-position[popover] {
|
|
3
3
|
padding: 0;
|
4
4
|
position: absolute;
|
5
5
|
min-width: 192px;
|
6
|
-
inset: auto;
|
7
6
|
overflow: visible;
|
8
7
|
background: none;
|
9
8
|
}
|
@@ -12,17 +11,6 @@ anchored-position[popover] {
|
|
12
11
|
display: flex;
|
13
12
|
}
|
14
13
|
|
15
|
-
anchored-position[popover]:not(.\:popover-open) {
|
16
|
-
display: none;
|
17
|
-
}
|
18
|
-
|
19
14
|
anchored-position.not-anchored::backdrop {
|
20
15
|
background-color: var(--overlay-backdrop-bgColor, var(--color-neutral-muted));
|
21
16
|
}
|
22
|
-
|
23
|
-
/* This reverts the declaration above for native popover, where `:popover-open` is supported */
|
24
|
-
@supports selector(:popover-open) {
|
25
|
-
anchored-position[popover]:not(.\:popover-open) {
|
26
|
-
display: revert;
|
27
|
-
}
|
28
|
-
}
|
@@ -32,8 +32,9 @@ const isPopoverOpen = (() => {
|
|
32
32
|
}
|
33
33
|
return (el) => (selector ? el.matches(selector) : setSelector(el));
|
34
34
|
})();
|
35
|
+
const TOOLTIP_ARROW_EDGE_OFFSET = 6;
|
35
36
|
const TOOLTIP_SR_ONLY_CLASS = 'sr-only';
|
36
|
-
const TOOLTIP_OFFSET =
|
37
|
+
const TOOLTIP_OFFSET = 10;
|
37
38
|
const DIRECTION_CLASSES = [
|
38
39
|
'tooltip-n',
|
39
40
|
'tooltip-s',
|
@@ -106,15 +107,33 @@ class ToolTipElement extends HTMLElement {
|
|
106
107
|
text-wrap: balance;
|
107
108
|
}
|
108
109
|
|
110
|
+
:host:before{
|
111
|
+
position: absolute;
|
112
|
+
z-index: 1000001;
|
113
|
+
color: var(--bgColor-emphasis, var(--color-neutral-emphasis-plus));
|
114
|
+
content: "";
|
115
|
+
border: 6px solid transparent;
|
116
|
+
opacity: 0;
|
117
|
+
}
|
118
|
+
|
109
119
|
@keyframes tooltip-appear {
|
110
120
|
from {
|
111
121
|
opacity: 0;
|
112
122
|
}
|
113
123
|
to {
|
114
|
-
opacity: 1
|
124
|
+
opacity: 1;
|
115
125
|
}
|
116
126
|
}
|
117
127
|
|
128
|
+
:host:after{
|
129
|
+
position: absolute;
|
130
|
+
display: block;
|
131
|
+
right: 0;
|
132
|
+
left: 0;
|
133
|
+
height: 12px;
|
134
|
+
content: "";
|
135
|
+
}
|
136
|
+
|
118
137
|
:host(:popover-open),
|
119
138
|
:host(:popover-open):before {
|
120
139
|
animation-name: tooltip-appear;
|
@@ -123,11 +142,65 @@ class ToolTipElement extends HTMLElement {
|
|
123
142
|
animation-timing-function: ease-in;
|
124
143
|
}
|
125
144
|
|
126
|
-
:host(.\\:popover-open)
|
145
|
+
:host(.\\:popover-open),
|
146
|
+
:host(.\\:popover-open):before {
|
127
147
|
animation-name: tooltip-appear;
|
128
148
|
animation-duration: .1s;
|
129
149
|
animation-fill-mode: forwards;
|
130
150
|
animation-timing-function: ease-in;
|
151
|
+
animation-delay: .4s;
|
152
|
+
}
|
153
|
+
|
154
|
+
:host(.tooltip-s):before,
|
155
|
+
:host(.tooltip-n):before {
|
156
|
+
right: 50%;
|
157
|
+
margin-right: -${TOOLTIP_ARROW_EDGE_OFFSET}px;
|
158
|
+
}
|
159
|
+
:host(.tooltip-s):before,
|
160
|
+
:host(.tooltip-se):before,
|
161
|
+
:host(.tooltip-sw):before {
|
162
|
+
bottom: 100%;
|
163
|
+
border-bottom-color: var(--bgColor-emphasis, var(--color-neutral-emphasis-plus));
|
164
|
+
}
|
165
|
+
:host(.tooltip-s):after,
|
166
|
+
:host(.tooltip-se):after,
|
167
|
+
:host(.tooltip-sw):after {
|
168
|
+
bottom: 100%
|
169
|
+
}
|
170
|
+
:host(.tooltip-n):before,
|
171
|
+
:host(.tooltip-ne):before,
|
172
|
+
:host(.tooltip-nw):before {
|
173
|
+
top: 100%;
|
174
|
+
border-top-color: var(--bgColor-emphasis, var(--color-neutral-emphasis-plus));
|
175
|
+
}
|
176
|
+
:host(.tooltip-n):after,
|
177
|
+
:host(.tooltip-ne):after,
|
178
|
+
:host(.tooltip-nw):after {
|
179
|
+
top: 100%;
|
180
|
+
}
|
181
|
+
:host(.tooltip-se):before,
|
182
|
+
:host(.tooltip-ne):before {
|
183
|
+
left: 0;
|
184
|
+
margin-left: ${TOOLTIP_ARROW_EDGE_OFFSET}px;
|
185
|
+
}
|
186
|
+
:host(.tooltip-sw):before,
|
187
|
+
:host(.tooltip-nw):before {
|
188
|
+
right: 0;
|
189
|
+
margin-right: ${TOOLTIP_ARROW_EDGE_OFFSET}px;
|
190
|
+
}
|
191
|
+
:host(.tooltip-w):before {
|
192
|
+
top: 50%;
|
193
|
+
bottom: 50%;
|
194
|
+
left: 100%;
|
195
|
+
margin-top: -6px;
|
196
|
+
border-left-color: var(--bgColor-emphasis, var(--color-neutral-emphasis-plus));
|
197
|
+
}
|
198
|
+
:host(.tooltip-e):before {
|
199
|
+
top: 50%;
|
200
|
+
right: 100%;
|
201
|
+
bottom: 50%;
|
202
|
+
margin-top: -6px;
|
203
|
+
border-right-color: var(--bgColor-emphasis, var(--color-neutral-emphasis-plus));
|
131
204
|
}
|
132
205
|
`;
|
133
206
|
}
|
@@ -21,8 +21,9 @@ const isPopoverOpen = (() => {
|
|
21
21
|
return (el: Element) => (selector ? el.matches(selector) : setSelector(el))
|
22
22
|
})()
|
23
23
|
|
24
|
+
const TOOLTIP_ARROW_EDGE_OFFSET = 6
|
24
25
|
const TOOLTIP_SR_ONLY_CLASS = 'sr-only'
|
25
|
-
const TOOLTIP_OFFSET =
|
26
|
+
const TOOLTIP_OFFSET = 10
|
26
27
|
|
27
28
|
type Direction = 'n' | 's' | 'e' | 'w' | 'ne' | 'se' | 'nw' | 'sw'
|
28
29
|
|
@@ -91,15 +92,33 @@ class ToolTipElement extends HTMLElement {
|
|
91
92
|
text-wrap: balance;
|
92
93
|
}
|
93
94
|
|
95
|
+
:host:before{
|
96
|
+
position: absolute;
|
97
|
+
z-index: 1000001;
|
98
|
+
color: var(--bgColor-emphasis, var(--color-neutral-emphasis-plus));
|
99
|
+
content: "";
|
100
|
+
border: 6px solid transparent;
|
101
|
+
opacity: 0;
|
102
|
+
}
|
103
|
+
|
94
104
|
@keyframes tooltip-appear {
|
95
105
|
from {
|
96
106
|
opacity: 0;
|
97
107
|
}
|
98
108
|
to {
|
99
|
-
opacity: 1
|
109
|
+
opacity: 1;
|
100
110
|
}
|
101
111
|
}
|
102
112
|
|
113
|
+
:host:after{
|
114
|
+
position: absolute;
|
115
|
+
display: block;
|
116
|
+
right: 0;
|
117
|
+
left: 0;
|
118
|
+
height: 12px;
|
119
|
+
content: "";
|
120
|
+
}
|
121
|
+
|
103
122
|
:host(:popover-open),
|
104
123
|
:host(:popover-open):before {
|
105
124
|
animation-name: tooltip-appear;
|
@@ -108,11 +127,65 @@ class ToolTipElement extends HTMLElement {
|
|
108
127
|
animation-timing-function: ease-in;
|
109
128
|
}
|
110
129
|
|
111
|
-
:host(.\\:popover-open)
|
130
|
+
:host(.\\:popover-open),
|
131
|
+
:host(.\\:popover-open):before {
|
112
132
|
animation-name: tooltip-appear;
|
113
133
|
animation-duration: .1s;
|
114
134
|
animation-fill-mode: forwards;
|
115
135
|
animation-timing-function: ease-in;
|
136
|
+
animation-delay: .4s;
|
137
|
+
}
|
138
|
+
|
139
|
+
:host(.tooltip-s):before,
|
140
|
+
:host(.tooltip-n):before {
|
141
|
+
right: 50%;
|
142
|
+
margin-right: -${TOOLTIP_ARROW_EDGE_OFFSET}px;
|
143
|
+
}
|
144
|
+
:host(.tooltip-s):before,
|
145
|
+
:host(.tooltip-se):before,
|
146
|
+
:host(.tooltip-sw):before {
|
147
|
+
bottom: 100%;
|
148
|
+
border-bottom-color: var(--bgColor-emphasis, var(--color-neutral-emphasis-plus));
|
149
|
+
}
|
150
|
+
:host(.tooltip-s):after,
|
151
|
+
:host(.tooltip-se):after,
|
152
|
+
:host(.tooltip-sw):after {
|
153
|
+
bottom: 100%
|
154
|
+
}
|
155
|
+
:host(.tooltip-n):before,
|
156
|
+
:host(.tooltip-ne):before,
|
157
|
+
:host(.tooltip-nw):before {
|
158
|
+
top: 100%;
|
159
|
+
border-top-color: var(--bgColor-emphasis, var(--color-neutral-emphasis-plus));
|
160
|
+
}
|
161
|
+
:host(.tooltip-n):after,
|
162
|
+
:host(.tooltip-ne):after,
|
163
|
+
:host(.tooltip-nw):after {
|
164
|
+
top: 100%;
|
165
|
+
}
|
166
|
+
:host(.tooltip-se):before,
|
167
|
+
:host(.tooltip-ne):before {
|
168
|
+
left: 0;
|
169
|
+
margin-left: ${TOOLTIP_ARROW_EDGE_OFFSET}px;
|
170
|
+
}
|
171
|
+
:host(.tooltip-sw):before,
|
172
|
+
:host(.tooltip-nw):before {
|
173
|
+
right: 0;
|
174
|
+
margin-right: ${TOOLTIP_ARROW_EDGE_OFFSET}px;
|
175
|
+
}
|
176
|
+
:host(.tooltip-w):before {
|
177
|
+
top: 50%;
|
178
|
+
bottom: 50%;
|
179
|
+
left: 100%;
|
180
|
+
margin-top: -6px;
|
181
|
+
border-left-color: var(--bgColor-emphasis, var(--color-neutral-emphasis-plus));
|
182
|
+
}
|
183
|
+
:host(.tooltip-e):before {
|
184
|
+
top: 50%;
|
185
|
+
right: 100%;
|
186
|
+
bottom: 50%;
|
187
|
+
margin-top: -6px;
|
188
|
+
border-right-color: var(--bgColor-emphasis, var(--color-neutral-emphasis-plus));
|
116
189
|
}
|
117
190
|
`
|
118
191
|
}
|
@@ -1 +1 @@
|
|
1
|
-
.PageHeader{border-bottom:var(--borderWidth-thin,max(1px,.0625rem)) solid var(--borderColor-muted,var(--color-border-muted));display:flex;flex-flow:
|
1
|
+
.PageHeader{border-bottom:var(--borderWidth-thin,max(1px,.0625rem)) solid var(--borderColor-muted,var(--color-border-muted));display:flex;flex-flow:column;margin-bottom:var(--stack-gap-normal,1rem);padding-bottom:var(--stack-padding-condensed,.5rem)}@media (max-width:767.98px){.PageHeader{border-bottom:0}}.PageHeader-titleBar{align-items:center;display:flex;flex-flow:row;justify-content:flex-end}.PageHeader-title{flex:1 1 auto;font-size:24px;font-weight:var(--base-text-weight-normal,400)}.PageHeader-title--large{font-size:var(--text-title-size-large,2rem)}.PageHeader-description{color:var(--fgColor-muted,var(--color-fg-muted));flex:1 100%;font-size:var(--text-body-size-medium,.875rem)}.PageHeader-actions{justify-content:flex-end;margin:var(--base-size-4,.25rem) 0 var(--base-size-4,.25rem) var(--base-size-4,.25rem)}.PageHeader-actions+.PageHeader-description{margin-top:var(--base-size-4,.25rem)}.PageHeader-breadcrumbs{display:block;margin-bottom:var(--base-size-8,.5rem);width:100%}.PageHeader-backButton{margin-right:var(--base-size-4,.25rem);margin-top:2px}
|
@@ -2,10 +2,13 @@
|
|
2
2
|
"name": "open_project/page_header",
|
3
3
|
"selectors": [
|
4
4
|
".PageHeader",
|
5
|
+
".PageHeader-titleBar",
|
5
6
|
".PageHeader-title",
|
6
7
|
".PageHeader-title--large",
|
7
8
|
".PageHeader-description",
|
8
9
|
".PageHeader-actions",
|
9
|
-
".PageHeader-actions+.PageHeader-description"
|
10
|
+
".PageHeader-actions+.PageHeader-description",
|
11
|
+
".PageHeader-breadcrumbs",
|
12
|
+
".PageHeader-backButton"
|
10
13
|
]
|
11
14
|
}
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"sources":["page_header.pcss"],"names":[],"mappings":"AAEA,YAIE,gHAAqE,CAHrE,YAAa,CAIb,
|
1
|
+
{"version":3,"sources":["page_header.pcss"],"names":[],"mappings":"AAEA,YAIE,gHAAqE,CAHrE,YAAa,CAIb,gBAAiB,CAFjB,0CAAsC,CADtC,mDAQF,CAHE,4BAPF,YAQI,eAEJ,CADE,CAGF,qBAIE,kBAAmB,CAHnB,YAAa,CACb,aAAc,CACd,wBAEF,CAEA,kBAGE,aAAc,CAFd,cAAe,CACf,8CAEF,CAEA,yBACE,2CACF,CAGA,wBAEE,gDAA2B,CAC3B,WAAY,CAFZ,8CAGF,CAGA,oBAEE,wBAAyB,CADzB,sFAMF,CAHE,4CACE,oCACF,CAGF,wBACE,aAAc,CAEd,sCAAiC,CADjC,UAEF,CAEA,uBAEE,sCAAgC,CADhC,cAEF","file":"page_header.css","sourcesContent":["/* OP PageHeader */\n\n.PageHeader {\n display: flex;\n padding-bottom: var(--stack-padding-condensed);\n margin-bottom: var(--stack-gap-normal);\n border-bottom: var(--borderWidth-thin) solid var(--borderColor-muted);\n flex-flow: column;\n\n @media (max-width: 767.98px) {\n border-bottom: 0;\n }\n}\n\n.PageHeader-titleBar {\n display: flex;\n flex-flow: row;\n justify-content: flex-end;\n align-items: center; /* Keep back button vertically aligned. */\n}\n\n.PageHeader-title {\n font-size: 24px;\n font-weight: var(--base-text-weight-normal);\n flex: 1 1 auto;\n}\n\n.PageHeader-title--large {\n font-size: var(--text-title-size-large);\n}\n\n/* One-liner of supporting text */\n.PageHeader-description {\n font-size: var(--text-body-size-medium);\n color: var(--fgColor-muted);\n flex: 1 100%;\n}\n\n/* Add 1 or 2 buttons to the right of the heading */\n.PageHeader-actions {\n margin: var(--base-size-4) 0 var(--base-size-4) var(--base-size-4);\n justify-content: flex-end;\n\n & + .PageHeader-description {\n margin-top: var(--base-size-4);\n }\n}\n\n.PageHeader-breadcrumbs {\n display: block;\n width: 100%;\n margin-bottom: var(--base-size-8);\n}\n\n.PageHeader-backButton {\n margin-top: 2px; /* to center align with label */\n margin-right: var(--base-size-4);\n}\n"]}
|
@@ -5,19 +5,24 @@
|
|
5
5
|
padding-bottom: var(--stack-padding-condensed);
|
6
6
|
margin-bottom: var(--stack-gap-normal);
|
7
7
|
border-bottom: var(--borderWidth-thin) solid var(--borderColor-muted);
|
8
|
-
flex-flow:
|
9
|
-
justify-content: flex-end; /* Keep actions right aligned. */
|
8
|
+
flex-flow: column;
|
10
9
|
|
11
10
|
@media (max-width: 767.98px) {
|
12
11
|
border-bottom: 0;
|
13
12
|
}
|
14
13
|
}
|
15
14
|
|
15
|
+
.PageHeader-titleBar {
|
16
|
+
display: flex;
|
17
|
+
flex-flow: row;
|
18
|
+
justify-content: flex-end;
|
19
|
+
align-items: center; /* Keep back button vertically aligned. */
|
20
|
+
}
|
21
|
+
|
16
22
|
.PageHeader-title {
|
17
23
|
font-size: 24px;
|
18
24
|
font-weight: var(--base-text-weight-normal);
|
19
25
|
flex: 1 1 auto;
|
20
|
-
order: 0;
|
21
26
|
}
|
22
27
|
|
23
28
|
.PageHeader-title--large {
|
@@ -29,17 +34,25 @@
|
|
29
34
|
font-size: var(--text-body-size-medium);
|
30
35
|
color: var(--fgColor-muted);
|
31
36
|
flex: 1 100%;
|
32
|
-
order: 2;
|
33
37
|
}
|
34
38
|
|
35
39
|
/* Add 1 or 2 buttons to the right of the heading */
|
36
40
|
.PageHeader-actions {
|
37
41
|
margin: var(--base-size-4) 0 var(--base-size-4) var(--base-size-4);
|
38
|
-
align-self: center;
|
39
42
|
justify-content: flex-end;
|
40
|
-
order: 1;
|
41
43
|
|
42
44
|
& + .PageHeader-description {
|
43
45
|
margin-top: var(--base-size-4);
|
44
46
|
}
|
45
47
|
}
|
48
|
+
|
49
|
+
.PageHeader-breadcrumbs {
|
50
|
+
display: block;
|
51
|
+
width: 100%;
|
52
|
+
margin-bottom: var(--base-size-8);
|
53
|
+
}
|
54
|
+
|
55
|
+
.PageHeader-backButton {
|
56
|
+
margin-top: 2px; /* to center align with label */
|
57
|
+
margin-right: var(--base-size-4);
|
58
|
+
}
|
@@ -13,6 +13,20 @@ module Primer
|
|
13
13
|
DEFAULT_HEADER_VARIANT
|
14
14
|
].freeze
|
15
15
|
|
16
|
+
DEFAULT_BACK_BUTTON_SIZE = :medium
|
17
|
+
BACK_BUTTON_SIZE_OPTIONS = [
|
18
|
+
:small,
|
19
|
+
DEFAULT_HEADER_VARIANT,
|
20
|
+
:large
|
21
|
+
].freeze
|
22
|
+
|
23
|
+
DEFAULT_BACK_BUTTON_ICON = "arrow-left"
|
24
|
+
BACK_BUTTON_ICON_OPTIONS = [
|
25
|
+
DEFAULT_BACK_BUTTON_ICON,
|
26
|
+
"chevron-left",
|
27
|
+
"triangle-left"
|
28
|
+
].freeze
|
29
|
+
|
16
30
|
status :open_project
|
17
31
|
|
18
32
|
# The title of the page header
|
@@ -50,6 +64,45 @@ module Primer
|
|
50
64
|
Primer::BaseComponent.new(**system_arguments)
|
51
65
|
}
|
52
66
|
|
67
|
+
# Optional back button prepend the title
|
68
|
+
#
|
69
|
+
# @param size [Symbol] <%= one_of(Primer::OpenProject::PageHeader::BACK_BUTTON_SIZE_OPTIONS) %>
|
70
|
+
# @param icon [String] <%= one_of(Primer::OpenProject::PageHeader::BACK_BUTTON_ICON_OPTIONS) %>
|
71
|
+
# @param system_arguments [Hash] <%= link_to_system_arguments_docs %>
|
72
|
+
renders_one :back_button, lambda { |
|
73
|
+
size: DEFAULT_BACK_BUTTON_SIZE,
|
74
|
+
icon: DEFAULT_BACK_BUTTON_ICON,
|
75
|
+
**system_arguments
|
76
|
+
|
|
77
|
+
deny_tag_argument(**system_arguments)
|
78
|
+
system_arguments[:tag] = :a
|
79
|
+
system_arguments[:scheme] = :invisible
|
80
|
+
system_arguments[:size] = fetch_or_fallback(BACK_BUTTON_SIZE_OPTIONS, size, DEFAULT_BACK_BUTTON_SIZE)
|
81
|
+
system_arguments[:icon] = fetch_or_fallback(BACK_BUTTON_ICON_OPTIONS, icon, DEFAULT_BACK_BUTTON_ICON)
|
82
|
+
system_arguments[:classes] = class_names(system_arguments[:classes], "PageHeader-backButton")
|
83
|
+
|
84
|
+
Primer::Beta::IconButton.new(**system_arguments)
|
85
|
+
}
|
86
|
+
|
87
|
+
# Optional breadcrumbs above the title row
|
88
|
+
#
|
89
|
+
# @param items [Array<String, Hash>] Items is an array of strings, hash {href, text} or an anchor tag string
|
90
|
+
# @param system_arguments [Hash] <%= link_to_system_arguments_docs %>
|
91
|
+
renders_one :breadcrumbs, lambda { |items, **system_arguments|
|
92
|
+
system_arguments[:classes] = class_names(system_arguments[:classes], "PageHeader-breadcrumbs")
|
93
|
+
render(Primer::Beta::Breadcrumbs.new(**system_arguments)) do |breadcrumbs|
|
94
|
+
items.each do |item|
|
95
|
+
item = anchor_string_to_object(item) if anchor_tag_string?(item)
|
96
|
+
|
97
|
+
if item.is_a?(String)
|
98
|
+
breadcrumbs.with_item(href: "#") { item }
|
99
|
+
else
|
100
|
+
breadcrumbs.with_item(href: item[:href]) { item[:text] }
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
}
|
105
|
+
|
53
106
|
def initialize(**system_arguments)
|
54
107
|
@system_arguments = deny_tag_argument(**system_arguments)
|
55
108
|
|
@@ -64,6 +117,23 @@ module Primer
|
|
64
117
|
def render?
|
65
118
|
title?
|
66
119
|
end
|
120
|
+
|
121
|
+
private
|
122
|
+
|
123
|
+
# transform anchor tag strings to {href, text} objects
|
124
|
+
# e.g "\u003ca href=\"/admin\"\u003eAdministration\u003c/a\u003e"
|
125
|
+
def anchor_string_to_object(html_string)
|
126
|
+
# Parse the HTML
|
127
|
+
doc = Nokogiri::HTML.fragment(html_string)
|
128
|
+
# Extract href and text
|
129
|
+
anchor = doc.at("a")
|
130
|
+
{ href: anchor["href"], text: anchor.text }
|
131
|
+
end
|
132
|
+
|
133
|
+
# Check if the item is an anchor tag string e.g "\u003ca href=\"/admin\"\u003eAdministration\u003c/a\u003e"
|
134
|
+
def anchor_tag_string?(item)
|
135
|
+
item.is_a?(String) && item.start_with?("\u003c")
|
136
|
+
end
|
67
137
|
end
|
68
138
|
end
|
69
139
|
end
|
data/lib/primer/accessibility.rb
CHANGED
@@ -8,9 +8,7 @@ module Primer
|
|
8
8
|
# Do not add to this list for any other reason!
|
9
9
|
IGNORED_PREVIEWS = [
|
10
10
|
Primer::Beta::MarkdownPreview,
|
11
|
-
Primer::Beta::AutoCompleteItemPreview
|
12
|
-
Primer::Alpha::RadioButtonPreview,
|
13
|
-
Primer::Alpha::CheckBoxPreview
|
11
|
+
Primer::Beta::AutoCompleteItemPreview
|
14
12
|
].freeze
|
15
13
|
|
16
14
|
# Skip `:region` which relates to preview page structure rather than individual component.
|
@@ -70,10 +70,15 @@ module Primer
|
|
70
70
|
render_erb_ignoring_markdown_code_fences(docs.base_docstring)
|
71
71
|
end
|
72
72
|
|
73
|
+
accessibility_docs =
|
74
|
+
if (accessibility_tag_text = docs.tags(:accessibility)&.first&.text)
|
75
|
+
render_erb_ignoring_markdown_code_fences(accessibility_tag_text)
|
76
|
+
end
|
77
|
+
|
73
78
|
memo[component] = {
|
74
79
|
"fully_qualified_name" => component.name,
|
75
80
|
"description" => description,
|
76
|
-
"accessibility_docs" =>
|
81
|
+
"accessibility_docs" => accessibility_docs,
|
77
82
|
"is_form_component" => docs.manifest_entry.form_component?,
|
78
83
|
"is_published" => docs.manifest_entry.published?,
|
79
84
|
"requires_js" => docs.manifest_entry.requires_js?,
|