openproject-primer_view_components 0.9.1 → 0.11.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 +40 -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/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/border_grid/cell.html.erb +3 -0
- data/app/components/primer/open_project/border_grid/cell.rb +25 -0
- data/app/components/primer/open_project/border_grid.css +1 -0
- data/app/components/primer/open_project/border_grid.css.json +11 -0
- data/app/components/primer/open_project/border_grid.css.map +1 -0
- data/app/components/primer/open_project/border_grid.html.erb +7 -0
- data/app/components/primer/open_project/border_grid.pcss +35 -0
- data/app/components/primer/open_project/border_grid.rb +36 -0
- data/app/components/primer/open_project/drag_handle.css +1 -0
- data/app/components/primer/open_project/drag_handle.css.json +6 -0
- data/app/components/primer/open_project/drag_handle.css.map +1 -0
- data/app/components/primer/open_project/drag_handle.html.erb +6 -0
- data/app/components/primer/open_project/drag_handle.pcss +6 -0
- data/app/components/primer/open_project/drag_handle.rb +28 -0
- data/app/components/primer/primer.pcss +2 -0
- data/lib/primer/view_components/linters/migrations/iconbutton_component.rb +36 -0
- data/lib/primer/view_components/version.rb +2 -2
- 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/border_grid_preview.rb +42 -0
- data/previews/primer/open_project/drag_handle_preview.rb +23 -0
- data/static/arguments.json +54 -0
- data/static/audited_at.json +3 -0
- data/static/classes.json +15 -0
- data/static/constants.json +13 -0
- data/static/info_arch.json +195 -0
- data/static/previews.json +94 -0
- data/static/statuses.json +3 -0
- metadata +20 -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 %>
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Primer
|
4
|
+
module OpenProject
|
5
|
+
class BorderGrid
|
6
|
+
# A single cell inside the BorderGrid
|
7
|
+
# A cell can contain for example an action list or a status badge
|
8
|
+
class Cell < Primer::Component
|
9
|
+
status :open_project
|
10
|
+
|
11
|
+
# @param system_arguments [Hash] <%= link_to_system_arguments_docs %>
|
12
|
+
def initialize(**system_arguments)
|
13
|
+
@system_arguments = system_arguments
|
14
|
+
@system_arguments[:tag] = "div"
|
15
|
+
|
16
|
+
@system_arguments[:classes] =
|
17
|
+
class_names(
|
18
|
+
@system_arguments[:classes],
|
19
|
+
"BorderGrid-cell"
|
20
|
+
)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
.BorderGrid{border-collapse:collapse;border-style:hidden;display:table;margin-bottom:-16px;margin-top:-16px;table-layout:fixed;width:100%}.BorderGrid .BorderGrid-cell{padding-bottom:16px;padding-top:16px}.BorderGrid--spacious{margin-bottom:-24px;margin-top:-24px}.BorderGrid--spacious .BorderGrid-cell{padding-bottom:24px;padding-top:24px}.BorderGrid-row{display:table-row}.BorderGrid-cell{border:1px solid var(--borderColor-muted,var(--color-border-muted));display:table-cell}
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"sources":["border_grid.pcss"],"names":[],"mappings":"AAEA,YAMI,wBAAyB,CACzB,mBAAmB,CANnB,aAAc,CAGd,mBAAoB,CADpB,gBAAiB,CAEjB,kBAAmB,CAHnB,UAMJ,CAEA,6BAEI,mBAAmB,CADnB,gBAEJ,CAEA,sBAEI,mBAAmB,CADnB,gBAEJ,CAEA,uCAEI,mBAAmB,CADnB,gBAEJ,CAEA,gBACI,iBACJ,CAEA,iBAEI,mEAAyC,CADzC,kBAEJ","file":"border_grid.css","sourcesContent":["/* CSS for BorderGrid */\n\n.BorderGrid {\n display: table;\n width: 100%;\n margin-top: -16px;\n margin-bottom: -16px;\n table-layout: fixed;\n border-collapse: collapse;\n border-style: hidden\n}\n\n.BorderGrid .BorderGrid-cell {\n padding-top: 16px;\n padding-bottom: 16px\n}\n\n.BorderGrid--spacious {\n margin-top: -24px;\n margin-bottom: -24px\n}\n\n.BorderGrid--spacious .BorderGrid-cell {\n padding-top: 24px;\n padding-bottom: 24px\n}\n\n.BorderGrid-row {\n display: table-row\n}\n\n.BorderGrid-cell {\n display: table-cell;\n border: 1px solid var(--borderColor-muted)\n}\n"]}
|
@@ -0,0 +1,35 @@
|
|
1
|
+
/* CSS for BorderGrid */
|
2
|
+
|
3
|
+
.BorderGrid {
|
4
|
+
display: table;
|
5
|
+
width: 100%;
|
6
|
+
margin-top: -16px;
|
7
|
+
margin-bottom: -16px;
|
8
|
+
table-layout: fixed;
|
9
|
+
border-collapse: collapse;
|
10
|
+
border-style: hidden
|
11
|
+
}
|
12
|
+
|
13
|
+
.BorderGrid .BorderGrid-cell {
|
14
|
+
padding-top: 16px;
|
15
|
+
padding-bottom: 16px
|
16
|
+
}
|
17
|
+
|
18
|
+
.BorderGrid--spacious {
|
19
|
+
margin-top: -24px;
|
20
|
+
margin-bottom: -24px
|
21
|
+
}
|
22
|
+
|
23
|
+
.BorderGrid--spacious .BorderGrid-cell {
|
24
|
+
padding-top: 24px;
|
25
|
+
padding-bottom: 24px
|
26
|
+
}
|
27
|
+
|
28
|
+
.BorderGrid-row {
|
29
|
+
display: table-row
|
30
|
+
}
|
31
|
+
|
32
|
+
.BorderGrid-cell {
|
33
|
+
display: table-cell;
|
34
|
+
border: 1px solid var(--borderColor-muted)
|
35
|
+
}
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Primer
|
4
|
+
module OpenProject
|
5
|
+
# A set of blocks that are shown below each other with separator lines in between
|
6
|
+
class BorderGrid < Primer::Component
|
7
|
+
status :open_project
|
8
|
+
|
9
|
+
# Use to render a block inside the grid
|
10
|
+
#
|
11
|
+
# @param system_arguments [Hash] <%= link_to_system_arguments_docs %>
|
12
|
+
renders_many :rows, lambda { |**system_arguments|
|
13
|
+
Primer::OpenProject::BorderGrid::Cell.new(**system_arguments)
|
14
|
+
}
|
15
|
+
|
16
|
+
# @param spacious [Boolean] Whether to add margin to the bottom of the component.
|
17
|
+
# @param system_arguments [Hash] <%= link_to_system_arguments_docs %>
|
18
|
+
def initialize(spacious: false, **system_arguments)
|
19
|
+
@system_arguments = system_arguments
|
20
|
+
@system_arguments[:tag] = "div"
|
21
|
+
@spacious = spacious
|
22
|
+
|
23
|
+
@system_arguments[:classes] =
|
24
|
+
class_names(
|
25
|
+
@system_arguments[:classes],
|
26
|
+
"BorderGrid",
|
27
|
+
"BorderGrid--spacious" => @spacious
|
28
|
+
)
|
29
|
+
end
|
30
|
+
|
31
|
+
def render?
|
32
|
+
rows.any?
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
.DragHandle{color:var(--fgColor-muted,var(--color-fg-muted));cursor:move}
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"sources":["drag_handle.pcss"],"names":[],"mappings":"AAEA,YAEI,gDAA2B,CAD3B,WAEJ","file":"drag_handle.css","sourcesContent":["/* CSS for DragHandle */\n\n.DragHandle {\n cursor: move;\n color: var(--fgColor-muted);\n}\n"]}
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Primer
|
4
|
+
module OpenProject
|
5
|
+
# Add a general description of component here
|
6
|
+
# Add additional usage considerations or best practices that may aid the user to use the component correctly.
|
7
|
+
# @accessibility Add any accessibility considerations
|
8
|
+
class DragHandle < Primer::Component
|
9
|
+
status :open_project
|
10
|
+
|
11
|
+
DEFAULT_SIZE = Primer::Beta::Octicon::SIZE_DEFAULT
|
12
|
+
SIZE_OPTIONS = Primer::Beta::Octicon::SIZE_OPTIONS
|
13
|
+
|
14
|
+
# @param system_arguments [Hash] <%= link_to_system_arguments_docs %>
|
15
|
+
def initialize(size: Primer::OpenProject::DragHandle::DEFAULT_SIZE, **system_arguments)
|
16
|
+
@system_arguments = system_arguments
|
17
|
+
@system_arguments[:tag] = "div"
|
18
|
+
@system_arguments[:classes] =
|
19
|
+
class_names(
|
20
|
+
@system_arguments[:classes],
|
21
|
+
"DragHandle"
|
22
|
+
)
|
23
|
+
|
24
|
+
@size = fetch_or_fallback(Primer::OpenProject::DragHandle::SIZE_OPTIONS, size, Primer::OpenProject::DragHandle::DEFAULT_SIZE)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -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 %>
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Setup Playground to use all available component props
|
4
|
+
# Setup Features to use individual component props and combinations
|
5
|
+
|
6
|
+
module Primer
|
7
|
+
module OpenProject
|
8
|
+
# @label BorderGrid
|
9
|
+
class BorderGridPreview < ViewComponent::Preview
|
10
|
+
|
11
|
+
# @label Playground
|
12
|
+
# @param spacious [Boolean] toggle
|
13
|
+
def playground(spacious: false)
|
14
|
+
render(Primer::OpenProject::BorderGrid.new(spacious: spacious)) do |grid|
|
15
|
+
grid.with_row { "Block 1" }
|
16
|
+
grid.with_row { "Block 2" }
|
17
|
+
grid.with_row { "Block 3" }
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
# @label Default Options
|
22
|
+
#
|
23
|
+
# @snapshot
|
24
|
+
def default()
|
25
|
+
render(Primer::OpenProject::BorderGrid.new) do |grid|
|
26
|
+
grid.with_row { "Block 1" }
|
27
|
+
grid.with_row { "Block 2" }
|
28
|
+
grid.with_row { "Block 3" }
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
# @label Spacious
|
33
|
+
def spacious()
|
34
|
+
render(Primer::OpenProject::BorderGrid.new(spacious: true)) do |grid|
|
35
|
+
grid.with_row { "Block 1" }
|
36
|
+
grid.with_row { "Block 2" }
|
37
|
+
grid.with_row { "Block 3" }
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Setup Playground to use all available component props
|
4
|
+
# Setup Features to use individual component props and combinations
|
5
|
+
|
6
|
+
module Primer
|
7
|
+
module OpenProject
|
8
|
+
# @label DragHandle
|
9
|
+
class DragHandlePreview < ViewComponent::Preview
|
10
|
+
# @label Default
|
11
|
+
# @snapshot
|
12
|
+
def default(size: :small)
|
13
|
+
render(Primer::OpenProject::DragHandle.new(size: size))
|
14
|
+
end
|
15
|
+
|
16
|
+
# @label Playground
|
17
|
+
# @param size [Symbol] select [xsmall, small, medium]
|
18
|
+
def playground(size: :small)
|
19
|
+
render(Primer::OpenProject::DragHandle.new(size: size))
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|