openproject-primer_view_components 0.9.0 → 0.10.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +37 -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/item.rb +3 -2
- data/app/components/primer/alpha/action_bar.rb +1 -5
- data/app/components/primer/alpha/overlay.css +1 -1
- data/app/components/primer/alpha/overlay.css.json +3 -1
- data/app/components/primer/alpha/overlay.css.map +1 -1
- data/app/components/primer/alpha/overlay.pcss +4 -0
- data/app/components/primer/alpha/tool_tip.js +28 -8
- data/app/components/primer/alpha/tool_tip.ts +27 -8
- data/app/components/primer/anchored_position.js +14 -5
- data/app/components/primer/anchored_position.ts +13 -4
- data/app/components/primer/beta/spinner.html.erb +1 -1
- data/app/components/primer/open_project/page_header.css +1 -1
- data/app/components/primer/open_project/page_header.css.json +1 -0
- data/app/components/primer/open_project/page_header.css.map +1 -1
- data/app/components/primer/open_project/page_header.pcss +6 -1
- data/app/components/primer/open_project/page_header.rb +13 -3
- data/lib/primer/view_components/linters/migrations/iconbutton_component.rb +36 -0
- data/lib/primer/view_components/version.rb +1 -1
- data/previews/primer/alpha/overlay_preview/in_an_action_menu.html.erb +13 -0
- data/previews/primer/alpha/overlay_preview.rb +5 -0
- data/previews/primer/open_project/page_header_preview.rb +13 -4
- data/static/arguments.json +11 -0
- data/static/audited_at.json +1 -0
- data/static/classes.json +3 -0
- data/static/constants.json +16 -0
- data/static/info_arch.json +129 -0
- data/static/previews.json +33 -7
- data/static/statuses.json +1 -0
- metadata +4 -2
@@ -7,7 +7,7 @@ module Primer
|
|
7
7
|
class ActionBar
|
8
8
|
# ActionBar::Item is an internal component that wraps the items in a div with the `ActionBar-item` class.
|
9
9
|
class Item < Primer::Component
|
10
|
-
def initialize
|
10
|
+
def initialize(item_content)
|
11
11
|
@system_arguments = {
|
12
12
|
tag: :div,
|
13
13
|
data: {
|
@@ -15,10 +15,11 @@ module Primer
|
|
15
15
|
},
|
16
16
|
classes: "ActionBar-item"
|
17
17
|
}
|
18
|
+
@item_content = item_content
|
18
19
|
end
|
19
20
|
|
20
21
|
def call
|
21
|
-
render(Primer::BaseComponent.new(**@system_arguments)) {
|
22
|
+
render(Primer::BaseComponent.new(**@system_arguments)) { render(@item_content) }
|
22
23
|
end
|
23
24
|
end
|
24
25
|
end
|
@@ -23,9 +23,7 @@ module Primer
|
|
23
23
|
c.with_leading_visual_icon(icon: icon)
|
24
24
|
end
|
25
25
|
|
26
|
-
|
27
|
-
render(Primer::Beta::IconButton.new(id: item_id, icon: icon, "aria-label": label, size: @size, scheme: :invisible, **system_arguments))
|
28
|
-
end
|
26
|
+
Item.new(Primer::Beta::IconButton.new(id: item_id, icon: icon, "aria-label": label, size: @size, scheme: :invisible, **system_arguments))
|
29
27
|
},
|
30
28
|
divider: lambda {
|
31
29
|
@action_menu.with_divider(hidden: true) if @overflow_menu
|
@@ -68,8 +66,6 @@ module Primer
|
|
68
66
|
system_arguments = {
|
69
67
|
**system_arguments,
|
70
68
|
hidden: true,
|
71
|
-
tag: :button,
|
72
|
-
type: "button",
|
73
69
|
"data-for": id,
|
74
70
|
"data-action": "click:action-bar#menuItemClick"
|
75
71
|
}
|
@@ -1 +1 @@
|
|
1
|
-
anchored-position[popover]{border-width:0;inset:auto;min-width:192px;overflow:visible;padding:0;position:absolute}.Overlay{display:flex}anchored-position[popover]:not(.\:popover-open){display:none}@supports selector(:popover-open){anchored-position[popover]:not(.\:popover-open){display:revert}}@supports selector(:open){anchored-position[popover]:not(.\:popover-open){display:revert}}
|
1
|
+
anchored-position[popover]{border-width:0;inset:auto;min-width:192px;overflow:visible;padding:0;position:absolute}.Overlay{display:flex}anchored-position[popover]:not(.\:popover-open){display:none}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))}@supports selector(:popover-open){anchored-position[popover]:not(.\:popover-open){display:revert}}@supports selector(:open){anchored-position[popover]:not(.\:popover-open){display:revert}}
|
@@ -3,6 +3,8 @@
|
|
3
3
|
"selectors": [
|
4
4
|
"anchored-position[popover]",
|
5
5
|
".Overlay",
|
6
|
-
"anchored-position[popover]:not(.\\:popover-open)"
|
6
|
+
"anchored-position[popover]:not(.\\:popover-open)",
|
7
|
+
"anchored-position.not-anchored::-webkit-backdrop",
|
8
|
+
"anchored-position.not-anchored::backdrop"
|
7
9
|
]
|
8
10
|
}
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"sources":["overlay.pcss"],"names":[],"mappings":"AAAA,2BACE,cAAe,CAIf,UAAW,CADX,eAAgB,CAEhB,gBAAiB,CAJjB,SAAU,CACV,iBAIF,CAEA,SACE,YACF,CAEA,gDACE,YACF,CAGA,kCACE,gDACE,cACF,CACF,CAGA,0BACE,gDACI,cACJ,CACF","file":"overlay.css","sourcesContent":["anchored-position[popover] {\n border-width: 0;\n padding: 0;\n position: absolute;\n min-width: 192px;\n inset: auto;\n overflow: visible;\n}\n\n.Overlay {\n display: flex;\n}\n\nanchored-position[popover]:not(.\\:popover-open) {\n display: none;\n}\n\n/* This reverts the declaration above for native popover, where `:popover-open` is supported */\n@supports selector(:popover-open) {\n anchored-position[popover]:not(.\\:popover-open) {\n display: revert;\n }\n}\n\n/* This reverts the declaration above for native popover, where `:open` is supported (Chrome 113, Safari TP) */\n@supports selector(:open) {\n anchored-position[popover]:not(.\\:popover-open) {\n display: revert;\n }\n}\n"]}
|
1
|
+
{"version":3,"sources":["overlay.pcss"],"names":[],"mappings":"AAAA,2BACE,cAAe,CAIf,UAAW,CADX,eAAgB,CAEhB,gBAAiB,CAJjB,SAAU,CACV,iBAIF,CAEA,SACE,YACF,CAEA,gDACE,YACF,CAEA,iDACE,2EACF,CAFA,yCACE,2EACF,CAGA,kCACE,gDACE,cACF,CACF,CAGA,0BACE,gDACI,cACJ,CACF","file":"overlay.css","sourcesContent":["anchored-position[popover] {\n border-width: 0;\n padding: 0;\n position: absolute;\n min-width: 192px;\n inset: auto;\n overflow: visible;\n}\n\n.Overlay {\n display: flex;\n}\n\nanchored-position[popover]:not(.\\:popover-open) {\n display: none;\n}\n\nanchored-position.not-anchored::backdrop {\n background-color: var(--overlay-backdrop-bgColor, var(--color-neutral-muted));\n}\n\n/* This reverts the declaration above for native popover, where `:popover-open` is supported */\n@supports selector(:popover-open) {\n anchored-position[popover]:not(.\\:popover-open) {\n display: revert;\n }\n}\n\n/* This reverts the declaration above for native popover, where `:open` is supported (Chrome 113, Safari TP) */\n@supports selector(:open) {\n anchored-position[popover]:not(.\\:popover-open) {\n display: revert;\n }\n}\n"]}
|
@@ -15,6 +15,10 @@ anchored-position[popover]:not(.\:popover-open) {
|
|
15
15
|
display: none;
|
16
16
|
}
|
17
17
|
|
18
|
+
anchored-position.not-anchored::backdrop {
|
19
|
+
background-color: var(--overlay-backdrop-bgColor, var(--color-neutral-muted));
|
20
|
+
}
|
21
|
+
|
18
22
|
/* This reverts the declaration above for native popover, where `:popover-open` is supported */
|
19
23
|
@supports selector(:popover-open) {
|
20
24
|
anchored-position[popover]:not(.\:popover-open) {
|
@@ -12,6 +12,26 @@ var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (
|
|
12
12
|
var _ToolTipElement_instances, _ToolTipElement_abortController, _ToolTipElement_align, _ToolTipElement_side, _ToolTipElement_allowUpdatePosition, _ToolTipElement_update, _ToolTipElement_updateControlReference, _ToolTipElement_updateDirection, _ToolTipElement_updatePosition;
|
13
13
|
import '@oddbird/popover-polyfill';
|
14
14
|
import { getAnchoredPosition } from '@primer/behaviors';
|
15
|
+
const isPopoverOpen = (() => {
|
16
|
+
let selector;
|
17
|
+
function setSelector(el) {
|
18
|
+
try {
|
19
|
+
selector = ':popover-open';
|
20
|
+
return el.matches(selector);
|
21
|
+
}
|
22
|
+
catch (_a) {
|
23
|
+
try {
|
24
|
+
selector = ':open';
|
25
|
+
return el.matches(':open');
|
26
|
+
}
|
27
|
+
catch (_b) {
|
28
|
+
selector = '.\\:popover-open';
|
29
|
+
return el.matches('.\\:popover-open');
|
30
|
+
}
|
31
|
+
}
|
32
|
+
}
|
33
|
+
return (el) => (selector ? el.matches(selector) : setSelector(el));
|
34
|
+
})();
|
15
35
|
const TOOLTIP_ARROW_EDGE_OFFSET = 6;
|
16
36
|
const TOOLTIP_SR_ONLY_CLASS = 'sr-only';
|
17
37
|
const TOOLTIP_OFFSET = 10;
|
@@ -29,7 +49,7 @@ function closeOpenTooltips(except) {
|
|
29
49
|
for (const tooltip of openTooltips) {
|
30
50
|
if (tooltip === except)
|
31
51
|
continue;
|
32
|
-
if (tooltip
|
52
|
+
if (isPopoverOpen(tooltip)) {
|
33
53
|
tooltip.hidePopover();
|
34
54
|
}
|
35
55
|
else {
|
@@ -207,16 +227,16 @@ class ToolTipElement extends HTMLElement {
|
|
207
227
|
}
|
208
228
|
/* @deprecated */
|
209
229
|
set hiddenFromView(value) {
|
210
|
-
if (value && this
|
230
|
+
if (value && isPopoverOpen(this)) {
|
211
231
|
this.hidePopover();
|
212
232
|
}
|
213
|
-
else if (!value && this
|
233
|
+
else if (!value && !isPopoverOpen(this)) {
|
214
234
|
this.showPopover();
|
215
235
|
}
|
216
236
|
}
|
217
237
|
/* @deprecated */
|
218
238
|
get hiddenFromView() {
|
219
|
-
return !this
|
239
|
+
return !isPopoverOpen(this);
|
220
240
|
}
|
221
241
|
connectedCallback() {
|
222
242
|
var _a, _b;
|
@@ -260,7 +280,7 @@ class ToolTipElement extends HTMLElement {
|
|
260
280
|
async handleEvent(event) {
|
261
281
|
if (!this.control)
|
262
282
|
return;
|
263
|
-
const showing = this
|
283
|
+
const showing = isPopoverOpen(this);
|
264
284
|
// Ensures that tooltip stays open when hovering between tooltip and element
|
265
285
|
// WCAG Success Criterion 1.4.13 Hoverable
|
266
286
|
const shouldShow = event.type === 'mouseenter' || event.type === 'focus';
|
@@ -272,10 +292,10 @@ class ToolTipElement extends HTMLElement {
|
|
272
292
|
const isOpeningOtherPopover = event.type === 'beforetoggle' && event.currentTarget !== this;
|
273
293
|
const shouldHide = isMouseLeaveFromButton || isEscapeKeydown || isMouseDownOnButton || isOpeningOtherPopover;
|
274
294
|
await Promise.resolve();
|
275
|
-
if (!showing && shouldShow && this
|
295
|
+
if (!showing && shouldShow && !isPopoverOpen(this)) {
|
276
296
|
this.showPopover();
|
277
297
|
}
|
278
|
-
else if (showing && shouldHide && this
|
298
|
+
else if (showing && shouldHide && isPopoverOpen(this)) {
|
279
299
|
this.hidePopover();
|
280
300
|
}
|
281
301
|
if (event.type === 'toggle') {
|
@@ -378,7 +398,7 @@ _ToolTipElement_abortController = new WeakMap(), _ToolTipElement_align = new Wea
|
|
378
398
|
}, _ToolTipElement_updatePosition = function _ToolTipElement_updatePosition() {
|
379
399
|
if (!this.control)
|
380
400
|
return;
|
381
|
-
if (!__classPrivateFieldGet(this, _ToolTipElement_allowUpdatePosition, "f") || !this
|
401
|
+
if (!__classPrivateFieldGet(this, _ToolTipElement_allowUpdatePosition, "f") || !isPopoverOpen(this))
|
382
402
|
return;
|
383
403
|
const position = getAnchoredPosition(this, this.control, {
|
384
404
|
side: __classPrivateFieldGet(this, _ToolTipElement_side, "f"),
|
@@ -2,6 +2,25 @@ import type {AnchorAlignment, AnchorSide} from '@primer/behaviors'
|
|
2
2
|
import '@oddbird/popover-polyfill'
|
3
3
|
import {getAnchoredPosition} from '@primer/behaviors'
|
4
4
|
|
5
|
+
const isPopoverOpen = (() => {
|
6
|
+
let selector: string
|
7
|
+
function setSelector(el: Element) {
|
8
|
+
try {
|
9
|
+
selector = ':popover-open'
|
10
|
+
return el.matches(selector)
|
11
|
+
} catch {
|
12
|
+
try {
|
13
|
+
selector = ':open'
|
14
|
+
return el.matches(':open')
|
15
|
+
} catch {
|
16
|
+
selector = '.\\:popover-open'
|
17
|
+
return el.matches('.\\:popover-open')
|
18
|
+
}
|
19
|
+
}
|
20
|
+
}
|
21
|
+
return (el: Element) => (selector ? el.matches(selector) : setSelector(el))
|
22
|
+
})()
|
23
|
+
|
5
24
|
const TOOLTIP_ARROW_EDGE_OFFSET = 6
|
6
25
|
const TOOLTIP_SR_ONLY_CLASS = 'sr-only'
|
7
26
|
const TOOLTIP_OFFSET = 10
|
@@ -22,7 +41,7 @@ const DIRECTION_CLASSES = [
|
|
22
41
|
function closeOpenTooltips(except?: Element) {
|
23
42
|
for (const tooltip of openTooltips) {
|
24
43
|
if (tooltip === except) continue
|
25
|
-
if (tooltip
|
44
|
+
if (isPopoverOpen(tooltip)) {
|
26
45
|
tooltip.hidePopover()
|
27
46
|
} else {
|
28
47
|
openTooltips.delete(tooltip)
|
@@ -206,16 +225,16 @@ class ToolTipElement extends HTMLElement {
|
|
206
225
|
|
207
226
|
/* @deprecated */
|
208
227
|
set hiddenFromView(value: true | false) {
|
209
|
-
if (value && this
|
228
|
+
if (value && isPopoverOpen(this)) {
|
210
229
|
this.hidePopover()
|
211
|
-
} else if (!value && this
|
230
|
+
} else if (!value && !isPopoverOpen(this)) {
|
212
231
|
this.showPopover()
|
213
232
|
}
|
214
233
|
}
|
215
234
|
|
216
235
|
/* @deprecated */
|
217
236
|
get hiddenFromView() {
|
218
|
-
return !this
|
237
|
+
return !isPopoverOpen(this)
|
219
238
|
}
|
220
239
|
|
221
240
|
connectedCallback() {
|
@@ -262,7 +281,7 @@ class ToolTipElement extends HTMLElement {
|
|
262
281
|
|
263
282
|
async handleEvent(event: Event) {
|
264
283
|
if (!this.control) return
|
265
|
-
const showing = this
|
284
|
+
const showing = isPopoverOpen(this)
|
266
285
|
|
267
286
|
// Ensures that tooltip stays open when hovering between tooltip and element
|
268
287
|
// WCAG Success Criterion 1.4.13 Hoverable
|
@@ -277,9 +296,9 @@ class ToolTipElement extends HTMLElement {
|
|
277
296
|
const shouldHide = isMouseLeaveFromButton || isEscapeKeydown || isMouseDownOnButton || isOpeningOtherPopover
|
278
297
|
|
279
298
|
await Promise.resolve()
|
280
|
-
if (!showing && shouldShow && this
|
299
|
+
if (!showing && shouldShow && !isPopoverOpen(this)) {
|
281
300
|
this.showPopover()
|
282
|
-
} else if (showing && shouldHide && this
|
301
|
+
} else if (showing && shouldHide && isPopoverOpen(this)) {
|
283
302
|
this.hidePopover()
|
284
303
|
}
|
285
304
|
|
@@ -377,7 +396,7 @@ class ToolTipElement extends HTMLElement {
|
|
377
396
|
|
378
397
|
#updatePosition() {
|
379
398
|
if (!this.control) return
|
380
|
-
if (!this.#allowUpdatePosition || !this
|
399
|
+
if (!this.#allowUpdatePosition || !isPopoverOpen(this)) return
|
381
400
|
|
382
401
|
const position = getAnchoredPosition(this, this.control, {
|
383
402
|
side: this.#side,
|
@@ -131,11 +131,20 @@ export default class AnchoredPositionElement extends HTMLElement {
|
|
131
131
|
cancelAnimationFrame(__classPrivateFieldGet(this, _AnchoredPositionElement_animationFrame, "f"));
|
132
132
|
__classPrivateFieldSet(this, _AnchoredPositionElement_animationFrame, requestAnimationFrame(() => {
|
133
133
|
const anchor = this.anchorElement;
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
134
|
+
this.classList.toggle('not-anchored', !anchor);
|
135
|
+
if (anchor) {
|
136
|
+
const { left, top } = getAnchoredPosition(this, anchor, this);
|
137
|
+
this.style.top = `${top}px`;
|
138
|
+
this.style.left = `${left}px`;
|
139
|
+
this.style.bottom = 'auto';
|
140
|
+
this.style.right = 'auto';
|
141
|
+
}
|
142
|
+
else {
|
143
|
+
this.style.top = '0';
|
144
|
+
this.style.left = '0';
|
145
|
+
this.style.bottom = '0';
|
146
|
+
this.style.right = '0';
|
147
|
+
}
|
139
148
|
}), "f");
|
140
149
|
}
|
141
150
|
}
|
@@ -133,10 +133,19 @@ export default class AnchoredPositionElement extends HTMLElement implements Posi
|
|
133
133
|
|
134
134
|
this.#animationFrame = requestAnimationFrame(() => {
|
135
135
|
const anchor = this.anchorElement
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
136
|
+
this.classList.toggle('not-anchored', !anchor)
|
137
|
+
if (anchor) {
|
138
|
+
const {left, top} = getAnchoredPosition(this, anchor, this)
|
139
|
+
this.style.top = `${top}px`
|
140
|
+
this.style.left = `${left}px`
|
141
|
+
this.style.bottom = 'auto'
|
142
|
+
this.style.right = 'auto'
|
143
|
+
} else {
|
144
|
+
this.style.top = '0'
|
145
|
+
this.style.left = '0'
|
146
|
+
this.style.bottom = '0'
|
147
|
+
this.style.right = '0'
|
148
|
+
}
|
140
149
|
})
|
141
150
|
}
|
142
151
|
}
|
@@ -1,4 +1,4 @@
|
|
1
1
|
<%= render Primer::BaseComponent.new(**@system_arguments) do %>
|
2
|
-
<circle cx="8" cy="8" r="7" stroke="currentColor" stroke-opacity="0.25" stroke-width="2" vector-effect="non-scaling-stroke" />
|
2
|
+
<circle cx="8" cy="8" r="7" stroke="currentColor" stroke-opacity="0.25" stroke-width="2" vector-effect="non-scaling-stroke" fill="none" />
|
3
3
|
<path d="M15 8a7.002 7.002 0 00-7-7" stroke="currentColor" stroke-width="2" stroke-linecap="round" vector-effect="non-scaling-stroke" />
|
4
4
|
<% end %>
|
@@ -1 +1 @@
|
|
1
|
-
.PageHeader{border-bottom:var(--borderWidth-thin,max(1px,.0625rem)) solid var(--borderColor-muted,var(--color-border-muted));display:flex;flex-flow:row wrap;justify-content:flex-end;margin-bottom:var(--stack-gap-normal,1rem);padding-bottom:var(--stack-padding-condensed,.5rem)}.PageHeader-title{flex:1 1 auto;order:0}.PageHeader-description{color:var(--fgColor-muted,var(--color-fg-muted));flex:1 100%;font-size:var(--text-body-size-medium,.875rem);order:2}.PageHeader-actions{align-self:center;justify-content:flex-end;margin:var(--base-size-4,.25rem) 0 var(--base-size-4,.25rem) var(--base-size-4,.25rem);order:1}.PageHeader-actions+.PageHeader-description{margin-top:var(--base-size-4,.25rem)}
|
1
|
+
.PageHeader{border-bottom:var(--borderWidth-thin,max(1px,.0625rem)) solid var(--borderColor-muted,var(--color-border-muted));display:flex;flex-flow:row wrap;justify-content:flex-end;margin-bottom:var(--stack-gap-normal,1rem);padding-bottom:var(--stack-padding-condensed,.5rem)}.PageHeader-title{flex:1 1 auto;font-size:24px;font-weight:var(--base-text-weight-normal,400);order:0}.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);order:2}.PageHeader-actions{align-self:center;justify-content:flex-end;margin:var(--base-size-4,.25rem) 0 var(--base-size-4,.25rem) var(--base-size-4,.25rem);order:1}.PageHeader-actions+.PageHeader-description{margin-top:var(--base-size-4,.25rem)}
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"sources":["page_header.pcss"],"names":[],"mappings":"AAEA,YAIE,gHAAqE,CAHrE,YAAa,CAIb,kBAAmB,CACnB,wBAAyB,CAHzB,0CAAsC,CADtC,mDAKF,
|
1
|
+
{"version":3,"sources":["page_header.pcss"],"names":[],"mappings":"AAEA,YAIE,gHAAqE,CAHrE,YAAa,CAIb,kBAAmB,CACnB,wBAAyB,CAHzB,0CAAsC,CADtC,mDAKF,CAEA,kBAGE,aAAc,CAFd,cAAe,CACf,8CAA2C,CAE3C,OACF,CAEA,yBACE,2CACF,CAGA,wBAEE,gDAA2B,CAC3B,WAAY,CAFZ,8CAAuC,CAGvC,OACF,CAGA,oBAEE,iBAAkB,CAClB,wBAAyB,CAFzB,sFAAkE,CAGlE,OAKF,CAHE,4CACE,oCACF","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: row wrap;\n justify-content: flex-end; /* Keep actions right aligned. */\n}\n\n.PageHeader-title {\n font-size: 24px;\n font-weight: var(--base-text-weight-normal);\n flex: 1 1 auto;\n order: 0;\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 order: 2;\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 align-self: center;\n justify-content: flex-end;\n order: 1;\n\n & + .PageHeader-description {\n margin-top: var(--base-size-4);\n }\n}\n"]}
|
@@ -9,12 +9,17 @@
|
|
9
9
|
justify-content: flex-end; /* Keep actions right aligned. */
|
10
10
|
}
|
11
11
|
|
12
|
-
/* <h2> sized heading with normal font weight */
|
13
12
|
.PageHeader-title {
|
13
|
+
font-size: 24px;
|
14
|
+
font-weight: var(--base-text-weight-normal);
|
14
15
|
flex: 1 1 auto;
|
15
16
|
order: 0;
|
16
17
|
}
|
17
18
|
|
19
|
+
.PageHeader-title--large {
|
20
|
+
font-size: var(--text-title-size-large);
|
21
|
+
}
|
22
|
+
|
18
23
|
/* One-liner of supporting text */
|
19
24
|
.PageHeader-description {
|
20
25
|
font-size: var(--text-body-size-medium);
|
@@ -5,7 +5,13 @@ module Primer
|
|
5
5
|
# A ViewComponent PageHeader inspired by the primer react variant
|
6
6
|
class PageHeader < Primer::Component
|
7
7
|
HEADING_TAG_OPTIONS = [:h1, :h2, :h3, :h4, :h5, :h6].freeze
|
8
|
-
HEADING_TAG_FALLBACK = :
|
8
|
+
HEADING_TAG_FALLBACK = :h2
|
9
|
+
|
10
|
+
DEFAULT_HEADER_VARIANT = :medium
|
11
|
+
HEADER_VARIANT_OPTIONS = [
|
12
|
+
:large,
|
13
|
+
DEFAULT_HEADER_VARIANT
|
14
|
+
].freeze
|
9
15
|
|
10
16
|
status :open_project
|
11
17
|
|
@@ -13,9 +19,13 @@ module Primer
|
|
13
19
|
#
|
14
20
|
# @param tag [Symbol] <%= one_of(Primer::Beta::Heading::TAG_OPTIONS) %>
|
15
21
|
# @param system_arguments [Hash] <%= link_to_system_arguments_docs %>
|
16
|
-
renders_one :title, lambda { |tag: :
|
22
|
+
renders_one :title, lambda { |tag: HEADING_TAG_FALLBACK, variant: DEFAULT_HEADER_VARIANT, **system_arguments|
|
17
23
|
system_arguments[:tag] = fetch_or_fallback(HEADING_TAG_OPTIONS, tag, HEADING_TAG_FALLBACK)
|
18
|
-
system_arguments[:classes] = class_names(
|
24
|
+
system_arguments[:classes] = class_names(
|
25
|
+
system_arguments[:classes],
|
26
|
+
"PageHeader-title",
|
27
|
+
"PageHeader-title--#{variant}"
|
28
|
+
)
|
19
29
|
|
20
30
|
Primer::BaseComponent.new(**system_arguments)
|
21
31
|
}
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Migrations
|
6
|
+
# Lint and autocorrect deprecated IconButton
|
7
|
+
class IconButtonComponent < RuboCop::Cop::Cop
|
8
|
+
INVALID_MESSAGE = <<~STR
|
9
|
+
`Primer::IconButton` is deprecated. Please use `Primer::Beta::IconButton` instead.
|
10
|
+
STR
|
11
|
+
|
12
|
+
def_node_matcher :icon_button, <<~PATTERN
|
13
|
+
(send $(const (const nil? :Primer) :IconButton) :new ...)
|
14
|
+
PATTERN
|
15
|
+
|
16
|
+
def_node_matcher :hash_with_box_value?, <<~PATTERN
|
17
|
+
(hash ... (pair (sym :box) (...)) ... )
|
18
|
+
PATTERN
|
19
|
+
|
20
|
+
def on_send(node)
|
21
|
+
return unless icon_button(node)
|
22
|
+
|
23
|
+
add_offense(node, message: INVALID_MESSAGE)
|
24
|
+
end
|
25
|
+
|
26
|
+
def autocorrect(node)
|
27
|
+
return if hash_with_box_value?(node.arguments.first)
|
28
|
+
|
29
|
+
lambda do |corrector|
|
30
|
+
corrector.replace(icon_button(node), "Primer::Beta::IconButton")
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
<%= render(Primer::Alpha::ActionMenu.new()) do |menu| %>
|
2
|
+
<% menu.with_show_button { "Menu" } %>
|
3
|
+
<% menu.with_item(label: "Open Overlay", content_arguments: { id: "overlay-show-my-overlay", popovertarget: "my-overlay" }) %>
|
4
|
+
<% end %>
|
5
|
+
<%= render(Primer::Alpha::Overlay.new(
|
6
|
+
id: "my-overlay",
|
7
|
+
title: "An overlay",
|
8
|
+
role: :dialog,
|
9
|
+
popover: "manual",
|
10
|
+
)) do |d| %>
|
11
|
+
<% d.with_header(title: "An overlay") %>
|
12
|
+
<% d.with_body { "This is an overlay" } %>
|
13
|
+
<% end %>
|
@@ -14,12 +14,21 @@ module Primer
|
|
14
14
|
end
|
15
15
|
end
|
16
16
|
|
17
|
-
|
18
17
|
# @label Playground
|
19
|
-
#
|
20
|
-
|
18
|
+
# @param variant [Symbol] select [medium, large]
|
19
|
+
# @param title [String] text
|
20
|
+
# @param description [String] text
|
21
|
+
def playground(variant: :medium, title: "Hello", description: "Last updated 5 minutes ago by XYZ.")
|
21
22
|
render(Primer::OpenProject::PageHeader.new) do |header|
|
22
|
-
header.with_title {
|
23
|
+
header.with_title(variant: variant) { title }
|
24
|
+
header.with_description { description }
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
# @label Large
|
29
|
+
def large_title
|
30
|
+
render(Primer::OpenProject::PageHeader.new) do |header|
|
31
|
+
header.with_title(variant: :large) { "Hello" }
|
23
32
|
header.with_description { "Last updated 5 minutes ago by XYZ." }
|
24
33
|
end
|
25
34
|
end
|
data/static/arguments.json
CHANGED
@@ -4423,6 +4423,17 @@
|
|
4423
4423
|
}
|
4424
4424
|
]
|
4425
4425
|
},
|
4426
|
+
{
|
4427
|
+
"component": "OpenProject::PageHeader",
|
4428
|
+
"status": "open_project",
|
4429
|
+
"a11y_reviewed": false,
|
4430
|
+
"short_name": "OpenProjectPageHeader",
|
4431
|
+
"source": "https://github.com/primer/view_components/tree/main/app/components/primer/open_project/page_header.rb",
|
4432
|
+
"lookbook": "https://primer.style/view-components/lookbook/inspect/primer/open_project/page_header/default/",
|
4433
|
+
"parameters": [
|
4434
|
+
|
4435
|
+
]
|
4436
|
+
},
|
4426
4437
|
{
|
4427
4438
|
"component": "Tooltip",
|
4428
4439
|
"status": "deprecated",
|
data/static/audited_at.json
CHANGED
data/static/classes.json
CHANGED
data/static/constants.json
CHANGED
@@ -1300,6 +1300,22 @@
|
|
1300
1300
|
},
|
1301
1301
|
"Primer::Navigation::TabComponent": {
|
1302
1302
|
},
|
1303
|
+
"Primer::OpenProject::PageHeader": {
|
1304
|
+
"DEFAULT_HEADER_VARIANT": "medium",
|
1305
|
+
"HEADER_VARIANT_OPTIONS": [
|
1306
|
+
"large",
|
1307
|
+
"medium"
|
1308
|
+
],
|
1309
|
+
"HEADING_TAG_FALLBACK": "h2",
|
1310
|
+
"HEADING_TAG_OPTIONS": [
|
1311
|
+
"h1",
|
1312
|
+
"h2",
|
1313
|
+
"h3",
|
1314
|
+
"h4",
|
1315
|
+
"h5",
|
1316
|
+
"h6"
|
1317
|
+
]
|
1318
|
+
},
|
1303
1319
|
"Primer::Tooltip": {
|
1304
1320
|
"ALIGN_DEFAULT": "default",
|
1305
1321
|
"ALIGN_MAPPING": {
|