openproject-primer_view_components 0.24.0 → 0.25.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.
Files changed (61) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +20 -0
  3. data/README.md +1 -0
  4. data/app/assets/javascripts/app/components/primer/open_project/page_header_element.d.ts +9 -0
  5. data/app/assets/javascripts/app/components/primer/primer.d.ts +1 -0
  6. data/app/assets/javascripts/primer_view_components.js +1 -1
  7. data/app/assets/javascripts/primer_view_components.js.map +1 -1
  8. data/app/assets/styles/primer_view_components.css +1 -1
  9. data/app/assets/styles/primer_view_components.css.map +1 -1
  10. data/app/components/primer/alpha/banner.css +1 -1
  11. data/app/components/primer/alpha/banner.css.map +1 -1
  12. data/app/components/primer/alpha/banner.pcss +4 -4
  13. data/app/components/primer/alpha/dialog.css +1 -1
  14. data/app/components/primer/alpha/dialog.css.json +1 -2
  15. data/app/components/primer/alpha/dialog.css.map +1 -1
  16. data/app/components/primer/alpha/dialog.pcss +8 -7
  17. data/app/components/primer/alpha/segmented_control.css +1 -1
  18. data/app/components/primer/alpha/segmented_control.css.map +1 -1
  19. data/app/components/primer/alpha/segmented_control.pcss +1 -0
  20. data/app/components/primer/alpha/tool_tip.js +46 -77
  21. data/app/components/primer/alpha/tool_tip.ts +46 -77
  22. data/app/components/primer/beta/flash.css +1 -1
  23. data/app/components/primer/beta/flash.css.map +1 -1
  24. data/app/components/primer/beta/flash.pcss +4 -4
  25. data/app/components/primer/open_project/page_header.css +1 -1
  26. data/app/components/primer/open_project/page_header.css.json +1 -0
  27. data/app/components/primer/open_project/page_header.css.map +1 -1
  28. data/app/components/primer/open_project/page_header.html.erb +6 -7
  29. data/app/components/primer/open_project/page_header.pcss +10 -0
  30. data/app/components/primer/open_project/page_header.rb +152 -34
  31. data/app/components/primer/open_project/page_header_element.d.ts +9 -0
  32. data/app/components/primer/open_project/page_header_element.js +23 -0
  33. data/app/components/primer/open_project/page_header_element.ts +25 -0
  34. data/app/components/primer/primer.d.ts +1 -0
  35. data/app/components/primer/primer.js +1 -0
  36. data/app/components/primer/primer.ts +1 -0
  37. data/lib/primer/view_components/version.rb +1 -1
  38. data/previews/primer/alpha/action_menu_preview.rb +1 -1
  39. data/previews/primer/alpha/tooltip_preview/tooltip_e.html.erb +6 -0
  40. data/previews/primer/alpha/tooltip_preview/tooltip_n.html.erb +6 -0
  41. data/previews/primer/alpha/tooltip_preview/tooltip_ne.html.erb +6 -0
  42. data/previews/primer/alpha/tooltip_preview/tooltip_nw.html.erb +6 -0
  43. data/previews/primer/alpha/tooltip_preview/tooltip_s.html.erb +6 -0
  44. data/previews/primer/alpha/tooltip_preview/tooltip_se.html.erb +6 -0
  45. data/previews/primer/alpha/tooltip_preview/tooltip_sw.html.erb +6 -0
  46. data/previews/primer/alpha/tooltip_preview/tooltip_w.html.erb +6 -0
  47. data/previews/primer/alpha/tooltip_preview.rb +80 -0
  48. data/previews/primer/open_project/border_grid_preview.rb +2 -2
  49. data/previews/primer/open_project/input_group_preview.rb +5 -5
  50. data/previews/primer/open_project/page_header_preview/actions.html.erb +16 -15
  51. data/previews/primer/open_project/page_header_preview/playground.html.erb +9 -24
  52. data/previews/primer/open_project/page_header_preview.rb +14 -36
  53. data/static/arguments.json +34 -1
  54. data/static/audited_at.json +1 -0
  55. data/static/classes.json +3 -0
  56. data/static/constants.json +9 -5
  57. data/static/info_arch.json +153 -48
  58. data/static/previews.json +104 -26
  59. data/static/statuses.json +1 -0
  60. metadata +14 -3
  61. data/previews/primer/open_project/page_header_preview/context_bar_actions.html.erb +0 -27
@@ -21,9 +21,7 @@ const isPopoverOpen = (() => {
21
21
  return (el: Element) => (selector ? el.matches(selector) : setSelector(el))
22
22
  })()
23
23
 
24
- const TOOLTIP_ARROW_EDGE_OFFSET = 6
25
24
  const TOOLTIP_SR_ONLY_CLASS = 'sr-only'
26
- const TOOLTIP_OFFSET = 10
27
25
 
28
26
  type Direction = 'n' | 's' | 'e' | 'w' | 'ne' | 'se' | 'nw' | 'sw'
29
27
 
@@ -69,6 +67,8 @@ class ToolTipElement extends HTMLElement {
69
67
  styles() {
70
68
  return `
71
69
  :host {
70
+ --tooltip-top: var(--tool-tip-position-top, 0);
71
+ --tooltip-left: var(--tool-tip-position-left, 0);
72
72
  padding: var(--overlay-paddingBlock-condensed) var(--overlay-padding-condensed) !important;
73
73
  font: var(--text-body-shorthand-small);
74
74
  color: var(--fgColor-onEmphasis, var(--color-fg-on-emphasis)) !important;
@@ -87,27 +87,29 @@ class ToolTipElement extends HTMLElement {
87
87
  word-wrap: break-word;
88
88
  white-space: normal;
89
89
  width: max-content !important;
90
- inset: var(--tool-tip-position-top, 0) auto auto var(--tool-tip-position-left, 0) !important;
90
+ inset: var(--tooltip-top) auto auto var(--tooltip-left) !important;
91
91
  overflow: visible !important;
92
92
  text-wrap: balance;
93
93
  }
94
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;
95
+ :host(:is(.tooltip-n, .tooltip-nw, .tooltip-ne)) {
96
+ --tooltip-top: calc(var(--tool-tip-position-top, 0) - var(--overlay-offset, 0.25rem));
97
+ --tooltip-left: var(--tool-tip-position-left);
102
98
  }
103
99
 
104
- @keyframes tooltip-appear {
105
- from {
106
- opacity: 0;
107
- }
108
- to {
109
- opacity: 1;
110
- }
100
+ :host(:is(.tooltip-s, .tooltip-sw, .tooltip-se)) {
101
+ --tooltip-top: calc(var(--tool-tip-position-top, 0) + var(--overlay-offset, 0.25rem));
102
+ --tooltip-left: var(--tool-tip-position-left);
103
+ }
104
+
105
+ :host(.tooltip-w) {
106
+ --tooltip-top: var(--tool-tip-position-top);
107
+ --tooltip-left: calc(var(--tool-tip-position-left, 0) - var(--overlay-offset, 0.25rem));
108
+ }
109
+
110
+ :host(.tooltip-e) {
111
+ --tooltip-top: var(--tool-tip-position-top);
112
+ --tooltip-left: calc(var(--tool-tip-position-left, 0) + var(--overlay-offset, 0.25rem));
111
113
  }
112
114
 
113
115
  :host:after{
@@ -119,73 +121,40 @@ class ToolTipElement extends HTMLElement {
119
121
  content: "";
120
122
  }
121
123
 
122
- :host(:popover-open),
123
- :host(:popover-open):before {
124
- animation-name: tooltip-appear;
125
- animation-duration: .1s;
126
- animation-fill-mode: forwards;
127
- animation-timing-function: ease-in;
128
- }
129
-
130
- :host(.\\:popover-open),
131
- :host(.\\:popover-open):before {
132
- animation-name: tooltip-appear;
133
- animation-duration: .1s;
134
- animation-fill-mode: forwards;
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
124
  :host(.tooltip-s):after,
151
125
  :host(.tooltip-se):after,
152
126
  :host(.tooltip-sw):after {
153
127
  bottom: 100%
154
128
  }
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
- }
129
+
161
130
  :host(.tooltip-n):after,
162
131
  :host(.tooltip-ne):after,
163
132
  :host(.tooltip-nw):after {
164
133
  top: 100%;
165
134
  }
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;
135
+
136
+ @keyframes tooltip-appear {
137
+ from {
138
+ opacity: 0;
139
+ }
140
+ to {
141
+ opacity: 1;
142
+ }
175
143
  }
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));
144
+
145
+ :host(:popover-open),
146
+ :host(:popover-open):before {
147
+ animation-name: tooltip-appear;
148
+ animation-duration: .1s;
149
+ animation-fill-mode: forwards;
150
+ animation-timing-function: ease-in;
182
151
  }
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));
152
+
153
+ :host(.\\:popover-open) {
154
+ animation-name: tooltip-appear;
155
+ animation-duration: .1s;
156
+ animation-fill-mode: forwards;
157
+ animation-timing-function: ease-in;
189
158
  }
190
159
 
191
160
  @media (forced-colors: active) {
@@ -398,25 +367,25 @@ class ToolTipElement extends HTMLElement {
398
367
  this.#align = 'center'
399
368
  this.#side = 'outside-top'
400
369
  } else if (direction === 'ne') {
401
- this.#align = 'start'
370
+ this.#align = 'end'
402
371
  this.#side = 'outside-top'
403
372
  } else if (direction === 'e') {
404
373
  this.#align = 'center'
405
374
  this.#side = 'outside-right'
406
375
  } else if (direction === 'se') {
407
- this.#align = 'start'
376
+ this.#align = 'end'
408
377
  this.#side = 'outside-bottom'
409
378
  } else if (direction === 's') {
410
379
  this.#align = 'center'
411
380
  this.#side = 'outside-bottom'
412
381
  } else if (direction === 'sw') {
413
- this.#align = 'end'
382
+ this.#align = 'start'
414
383
  this.#side = 'outside-bottom'
415
384
  } else if (direction === 'w') {
416
385
  this.#align = 'center'
417
386
  this.#side = 'outside-left'
418
387
  } else if (direction === 'nw') {
419
- this.#align = 'end'
388
+ this.#align = 'start'
420
389
  this.#side = 'outside-top'
421
390
  }
422
391
  }
@@ -428,7 +397,7 @@ class ToolTipElement extends HTMLElement {
428
397
  const position = getAnchoredPosition(this, this.control, {
429
398
  side: this.#side,
430
399
  align: this.#align,
431
- anchorOffset: TOOLTIP_OFFSET,
400
+ anchorOffset: 0,
432
401
  })
433
402
  const anchorSide = position.anchorSide
434
403
  const align = position.anchorAlign
@@ -1 +1 @@
1
- .flash:not(.Banner){background-color:var(--bgColor-accent-muted,var(--color-accent-subtle));border-color:var(--borderColor-accent-muted,var(--color-accent-muted));border-radius:var(--borderRadius-medium,.375rem);border-style:solid;border-width:var(--borderWidth-thin,max(1px,.0625rem));color:var(--fgColor-default,var(--color-fg-default));padding:var(--base-size-20,1.25rem) var(--control-medium-paddingInline-spacious,1rem);position:relative}.flash:not(.Banner) .octicon{color:var(--fgColor-accent,var(--color-accent-fg));margin-right:var(--base-size-12,.75rem)}.flash:not(.Banner) p:last-child{margin-bottom:0}.flash-messages{margin-bottom:var(--stack-gap-spacious,1.5rem)}.flash-close:not(.Banner-close){-webkit-appearance:none;appearance:none;background:none;border:0;cursor:pointer;float:right;margin-top:calc(var(--base-size-4,.25rem)*-1);text-align:center}.flash-close:not(.Banner-close):hover{opacity:.7}.flash-close:not(.Banner-close):active{opacity:.5}.flash-close:not(.Banner-close) .octicon{margin-right:0}.flash-action:not(.Banner-actions){background-clip:padding-box;float:right;margin-left:var(--stack-gap-spacious,1.5rem);margin-top:-3px}.flash-action.btn:not(.Banner-actions) .octicon{color:var(--fgColor-muted,var(--color-fg-muted));margin-right:var(--control-small-gap,.25rem)}.flash-action.btn-primary:not(.Banner-actions){background-clip:initial}.flash-action.btn-primary:not(.Banner-actions) .octicon{color:inherit}.flash-warn:not(.Banner){background-color:var(--bgColor-attention-muted,var(--color-attention-subtle));border-color:var(--borderColor-attention-muted,var(--color-attention-muted));color:var(--fgColor-default,var(--color-fg-default))}.flash-warn:not(.Banner) .octicon{color:var(--fgColor-attention,var(--color-attention-fg))}.flash-error:not(.Banner){background-color:var(--bgColor-danger-muted,var(--color-danger-subtle));border-color:var(--borderColor-danger-muted,var(--color-danger-muted));color:var(--fgColor-default,var(--color-fg-default))}.flash-error:not(.Banner) .octicon{color:var(--fgColor-danger,var(--color-danger-fg))}.flash-success:not(.Banner){background-color:var(--bgColor-success-muted,var(--color-success-subtle));border-color:var(--borderColor-success-muted,var(--color-success-muted));color:var(--fgColor-default,var(--color-fg-default))}.flash-success:not(.Banner) .octicon{color:var(--fgColor-success,var(--color-success-fg))}.flash-full:not(.Banner){border-radius:0;border-width:var(--borderWidth-thin,max(1px,.0625rem)) 0;margin-top:calc(var(--borderWidth-thin,max(1px, .0625rem))*-1)}.flash-banner{border-left:0;border-radius:0;border-right:0;border-top:0;position:fixed;top:0;width:100%;z-index:90}.flash-banner,.flash-full{background-color:var(--bgColor-default,var(--color-canvas-default))}.warning{background-color:var(--bgColor-attention-muted,var(--color-attention-subtle));font-weight:var(--base-text-weight-semibold,600);margin-bottom:.8em;padding:.5em}
1
+ .flash:not(.Banner){background-image:linear-gradient(var(--bgColor-accent-muted,var(--color-accent-subtle)),var(--bgColor-accent-muted,var(--color-accent-subtle)));border-color:var(--borderColor-accent-muted,var(--color-accent-muted));border-radius:var(--borderRadius-medium,.375rem);border-style:solid;border-width:var(--borderWidth-thin,max(1px,.0625rem));color:var(--fgColor-default,var(--color-fg-default));padding:var(--base-size-20,1.25rem) var(--control-medium-paddingInline-spacious,1rem);position:relative}.flash:not(.Banner) .octicon{color:var(--fgColor-accent,var(--color-accent-fg));margin-right:var(--base-size-12,.75rem)}.flash:not(.Banner) p:last-child{margin-bottom:0}.flash-messages{margin-bottom:var(--stack-gap-spacious,1.5rem)}.flash-close:not(.Banner-close){-webkit-appearance:none;appearance:none;background:none;border:0;cursor:pointer;float:right;margin-top:calc(var(--base-size-4,.25rem)*-1);text-align:center}.flash-close:not(.Banner-close):hover{opacity:.7}.flash-close:not(.Banner-close):active{opacity:.5}.flash-close:not(.Banner-close) .octicon{margin-right:0}.flash-action:not(.Banner-actions){background-clip:padding-box;float:right;margin-left:var(--stack-gap-spacious,1.5rem);margin-top:-3px}.flash-action.btn:not(.Banner-actions) .octicon{color:var(--fgColor-muted,var(--color-fg-muted));margin-right:var(--control-small-gap,.25rem)}.flash-action.btn-primary:not(.Banner-actions){background-clip:initial}.flash-action.btn-primary:not(.Banner-actions) .octicon{color:inherit}.flash-warn:not(.Banner){background-image:linear-gradient(var(--bgColor-attention-muted,var(--color-attention-subtle)),var(--bgColor-attention-muted,var(--color-attention-subtle)));border-color:var(--borderColor-attention-muted,var(--color-attention-muted));color:var(--fgColor-default,var(--color-fg-default))}.flash-warn:not(.Banner) .octicon{color:var(--fgColor-attention,var(--color-attention-fg))}.flash-error:not(.Banner){background-image:linear-gradient(var(--bgColor-danger-muted,var(--color-danger-subtle)),var(--bgColor-danger-muted,var(--color-danger-subtle)));border-color:var(--borderColor-danger-muted,var(--color-danger-muted));color:var(--fgColor-default,var(--color-fg-default))}.flash-error:not(.Banner) .octicon{color:var(--fgColor-danger,var(--color-danger-fg))}.flash-success:not(.Banner){background-image:linear-gradient(var(--bgColor-success-muted,var(--color-success-subtle)),var(--bgColor-success-muted,var(--color-success-subtle)));border-color:var(--borderColor-success-muted,var(--color-success-muted));color:var(--fgColor-default,var(--color-fg-default))}.flash-success:not(.Banner) .octicon{color:var(--fgColor-success,var(--color-success-fg))}.flash-full:not(.Banner){border-radius:0;border-width:var(--borderWidth-thin,max(1px,.0625rem)) 0;margin-top:calc(var(--borderWidth-thin,max(1px, .0625rem))*-1)}.flash-banner{border-left:0;border-radius:0;border-right:0;border-top:0;position:fixed;top:0;width:100%;z-index:90}.flash-banner,.flash-full{background-color:var(--bgColor-default,var(--color-canvas-default))}.warning{background-color:var(--bgColor-attention-muted,var(--color-attention-subtle));font-weight:var(--base-text-weight-semibold,600);margin-bottom:.8em;padding:.5em}
@@ -1 +1 @@
1
- {"version":3,"sources":["flash.pcss"],"names":[],"mappings":"AAGA,oBASE,uEAA6C,CAC7C,sEAA6C,CAL7C,gDAAyC,CAFzC,kBAAmB,CACnB,sDAAqC,CAIrC,oDAA6B,CAN7B,qFAAyE,CADzE,iBAmBF,CARE,6BACE,kDAA4B,CAC5B,uCACF,CAEA,iCACE,eACF,CAIF,gBACE,8CACF,CAGA,gCASE,uBAAgB,CAAhB,eAAgB,CAFhB,eAAgB,CAChB,QAAS,CAJT,cAAe,CAHf,WAAY,CACZ,6CAAyC,CACzC,iBAmBF,CAXE,sCACE,UACF,CAEA,uCACE,UACF,CAEA,yCACE,cACF,CAIF,mCAIE,2BAA4B,CAH5B,WAAY,CAEZ,4CAAsC,CADtC,eAgBF,CAZE,gDAEE,gDAA2B,CAD3B,4CAEF,CAEA,+CACE,uBAKF,CAHE,wDACE,aACF,CAMJ,yBAEE,6EAAgD,CAChD,4EAAgD,CAFhD,oDAOF,CAHE,kCACE,wDACF,CAGF,0BAEE,uEAA6C,CAC7C,sEAA6C,CAF7C,oDAOF,CAHE,mCACE,kDACF,CAGF,4BAEE,yEAA8C,CAC9C,wEAA8C,CAF9C,oDAOF,CAHE,qCACE,oDACF,CAKF,yBAGE,eAAgB,CADhB,wDAAuC,CADvC,8DAGF,CAGA,cAOE,aAAc,CACd,eAAgB,CAFhB,cAAe,CADf,YAAa,CAJb,cAAe,CACf,KAAM,CAEN,UAAW,CADX,UAMF,CAGA,0BAEE,mEACF,CAGA,SAIE,6EAAgD,CADhD,gDAA6C,CAD7C,kBAAoB,CADpB,YAIF","file":"flash.css","sourcesContent":["/* flash */\n\n/* Default flash */\n.flash:not(.Banner) {\n position: relative;\n padding: var(--base-size-20) var(--control-medium-paddingInline-spacious);\n border-style: solid;\n border-width: var(--borderWidth-thin);\n border-radius: var(--borderRadius-medium);\n\n /* Default color */\n color: var(--fgColor-default);\n background-color: var(--bgColor-accent-muted);\n border-color: var(--borderColor-accent-muted);\n\n & .octicon {\n color: var(--fgColor-accent);\n margin-right: var(--base-size-12);\n }\n\n & p:last-child {\n margin-bottom: 0;\n }\n}\n\n/* Contain the flash messages */\n.flash-messages {\n margin-bottom: var(--stack-gap-spacious);\n}\n\n/* Close button */\n.flash-close:not(.Banner-close) {\n float: right;\n margin-top: calc(var(--base-size-4) * -1);\n text-align: center;\n cursor: pointer;\n\n /* Undo `<button>` styles */\n background: none;\n border: 0;\n appearance: none;\n\n &:hover {\n opacity: 0.7;\n }\n\n &:active {\n opacity: 0.5;\n }\n\n & .octicon {\n margin-right: 0;\n }\n}\n\n/* Action button */\n.flash-action:not(.Banner-actions) {\n float: right;\n margin-top: -3px;\n margin-left: var(--stack-gap-spacious);\n background-clip: padding-box;\n\n &.btn .octicon {\n margin-right: var(--control-small-gap);\n color: var(--fgColor-muted);\n }\n\n &.btn-primary {\n background-clip: border-box;\n\n & .octicon {\n color: inherit;\n }\n }\n}\n\n/* Color variations */\n\n.flash-warn:not(.Banner) {\n color: var(--fgColor-default);\n background-color: var(--bgColor-attention-muted);\n border-color: var(--borderColor-attention-muted);\n\n & .octicon {\n color: var(--fgColor-attention);\n }\n}\n\n.flash-error:not(.Banner) {\n color: var(--fgColor-default);\n background-color: var(--bgColor-danger-muted);\n border-color: var(--borderColor-danger-muted);\n\n & .octicon {\n color: var(--fgColor-danger);\n }\n}\n\n.flash-success:not(.Banner) {\n color: var(--fgColor-default);\n background-color: var(--bgColor-success-muted);\n border-color: var(--borderColor-success-muted);\n\n & .octicon {\n color: var(--fgColor-success);\n }\n}\n\n/* Layout variations */\n\n.flash-full:not(.Banner) {\n margin-top: calc(var(--borderWidth-thin) * -1);\n border-width: var(--borderWidth-thin) 0;\n border-radius: 0;\n}\n\n/* A banner rendered at the top of the page. */\n.flash-banner {\n position: fixed;\n top: 0;\n z-index: 90;\n width: 100%;\n border-top: 0;\n border-right: 0;\n border-left: 0;\n border-radius: 0;\n}\n\n/* Makes sure the background is opaque to cover any content underneath */\n.flash-full,\n.flash-banner {\n background-color: var(--bgColor-default);\n}\n\n/* FIXME deprecate this */\n.warning {\n padding: 0.5em;\n margin-bottom: 0.8em;\n font-weight: var(--base-text-weight-semibold);\n background-color: var(--bgColor-attention-muted);\n}\n"]}
1
+ {"version":3,"sources":["flash.pcss"],"names":[],"mappings":"AAGA,oBASE,+IAA2F,CAC3F,sEAA6C,CAL7C,gDAAyC,CAFzC,kBAAmB,CACnB,sDAAqC,CAIrC,oDAA6B,CAN7B,qFAAyE,CADzE,iBAmBF,CARE,6BACE,kDAA4B,CAC5B,uCACF,CAEA,iCACE,eACF,CAIF,gBACE,8CACF,CAGA,gCASE,uBAAgB,CAAhB,eAAgB,CAFhB,eAAgB,CAChB,QAAS,CAJT,cAAe,CAHf,WAAY,CACZ,6CAAyC,CACzC,iBAmBF,CAXE,sCACE,UACF,CAEA,uCACE,UACF,CAEA,yCACE,cACF,CAIF,mCAIE,2BAA4B,CAH5B,WAAY,CAEZ,4CAAsC,CADtC,eAgBF,CAZE,gDAEE,gDAA2B,CAD3B,4CAEF,CAEA,+CACE,uBAKF,CAHE,wDACE,aACF,CAMJ,yBAEE,2JAAiG,CACjG,4EAAgD,CAFhD,oDAOF,CAHE,kCACE,wDACF,CAGF,0BAEE,+IAA2F,CAC3F,sEAA6C,CAF7C,oDAOF,CAHE,mCACE,kDACF,CAGF,4BAEE,mJAA6F,CAC7F,wEAA8C,CAF9C,oDAOF,CAHE,qCACE,oDACF,CAKF,yBAGE,eAAgB,CADhB,wDAAuC,CADvC,8DAGF,CAGA,cAOE,aAAc,CACd,eAAgB,CAFhB,cAAe,CADf,YAAa,CAJb,cAAe,CACf,KAAM,CAEN,UAAW,CADX,UAMF,CAGA,0BAEE,mEACF,CAGA,SAIE,6EAAgD,CADhD,gDAA6C,CAD7C,kBAAoB,CADpB,YAIF","file":"flash.css","sourcesContent":["/* flash */\n\n/* Default flash */\n.flash:not(.Banner) {\n position: relative;\n padding: var(--base-size-20) var(--control-medium-paddingInline-spacious);\n border-style: solid;\n border-width: var(--borderWidth-thin);\n border-radius: var(--borderRadius-medium);\n\n /* Default color */\n color: var(--fgColor-default);\n background-image: linear-gradient(var(--bgColor-accent-muted), var(--bgColor-accent-muted));\n border-color: var(--borderColor-accent-muted);\n\n & .octicon {\n color: var(--fgColor-accent);\n margin-right: var(--base-size-12);\n }\n\n & p:last-child {\n margin-bottom: 0;\n }\n}\n\n/* Contain the flash messages */\n.flash-messages {\n margin-bottom: var(--stack-gap-spacious);\n}\n\n/* Close button */\n.flash-close:not(.Banner-close) {\n float: right;\n margin-top: calc(var(--base-size-4) * -1);\n text-align: center;\n cursor: pointer;\n\n /* Undo `<button>` styles */\n background: none;\n border: 0;\n appearance: none;\n\n &:hover {\n opacity: 0.7;\n }\n\n &:active {\n opacity: 0.5;\n }\n\n & .octicon {\n margin-right: 0;\n }\n}\n\n/* Action button */\n.flash-action:not(.Banner-actions) {\n float: right;\n margin-top: -3px;\n margin-left: var(--stack-gap-spacious);\n background-clip: padding-box;\n\n &.btn .octicon {\n margin-right: var(--control-small-gap);\n color: var(--fgColor-muted);\n }\n\n &.btn-primary {\n background-clip: border-box;\n\n & .octicon {\n color: inherit;\n }\n }\n}\n\n/* Color variations */\n\n.flash-warn:not(.Banner) {\n color: var(--fgColor-default);\n background-image: linear-gradient(var(--bgColor-attention-muted), var(--bgColor-attention-muted));\n border-color: var(--borderColor-attention-muted);\n\n & .octicon {\n color: var(--fgColor-attention);\n }\n}\n\n.flash-error:not(.Banner) {\n color: var(--fgColor-default);\n background-image: linear-gradient(var(--bgColor-danger-muted), var(--bgColor-danger-muted));\n border-color: var(--borderColor-danger-muted);\n\n & .octicon {\n color: var(--fgColor-danger);\n }\n}\n\n.flash-success:not(.Banner) {\n color: var(--fgColor-default);\n background-image: linear-gradient(var(--bgColor-success-muted), var(--bgColor-success-muted));\n border-color: var(--borderColor-success-muted);\n\n & .octicon {\n color: var(--fgColor-success);\n }\n}\n\n/* Layout variations */\n\n.flash-full:not(.Banner) {\n margin-top: calc(var(--borderWidth-thin) * -1);\n border-width: var(--borderWidth-thin) 0;\n border-radius: 0;\n}\n\n/* A banner rendered at the top of the page. */\n.flash-banner {\n position: fixed;\n top: 0;\n z-index: 90;\n width: 100%;\n border-top: 0;\n border-right: 0;\n border-left: 0;\n border-radius: 0;\n}\n\n/* Makes sure the background is opaque to cover any content underneath */\n.flash-full,\n.flash-banner {\n background-color: var(--bgColor-default);\n}\n\n/* FIXME deprecate this */\n.warning {\n padding: 0.5em;\n margin-bottom: 0.8em;\n font-weight: var(--base-text-weight-semibold);\n background-color: var(--bgColor-attention-muted);\n}\n"]}
@@ -10,7 +10,7 @@
10
10
 
11
11
  /* Default color */
12
12
  color: var(--fgColor-default);
13
- background-color: var(--bgColor-accent-muted);
13
+ background-image: linear-gradient(var(--bgColor-accent-muted), var(--bgColor-accent-muted));
14
14
  border-color: var(--borderColor-accent-muted);
15
15
 
16
16
  & .octicon {
@@ -78,7 +78,7 @@
78
78
 
79
79
  .flash-warn:not(.Banner) {
80
80
  color: var(--fgColor-default);
81
- background-color: var(--bgColor-attention-muted);
81
+ background-image: linear-gradient(var(--bgColor-attention-muted), var(--bgColor-attention-muted));
82
82
  border-color: var(--borderColor-attention-muted);
83
83
 
84
84
  & .octicon {
@@ -88,7 +88,7 @@
88
88
 
89
89
  .flash-error:not(.Banner) {
90
90
  color: var(--fgColor-default);
91
- background-color: var(--bgColor-danger-muted);
91
+ background-image: linear-gradient(var(--bgColor-danger-muted), var(--bgColor-danger-muted));
92
92
  border-color: var(--borderColor-danger-muted);
93
93
 
94
94
  & .octicon {
@@ -98,7 +98,7 @@
98
98
 
99
99
  .flash-success:not(.Banner) {
100
100
  color: var(--fgColor-default);
101
- background-color: var(--bgColor-success-muted);
101
+ background-image: linear-gradient(var(--bgColor-success-muted), var(--bgColor-success-muted));
102
102
  border-color: var(--borderColor-success-muted);
103
103
 
104
104
  & .octicon {
@@ -1 +1 @@
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)}.PageHeader-contextBar,.PageHeader-titleBar{align-items:center;display:flex;flex-flow:row;justify-content:flex-end}.PageHeader-titleBar{margin-bottom:var(--space-xsmall,.25rem)}.PageHeader-title{flex:1 1 auto;font-size:var(--text-title-size-medium,1.25rem);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{align-items:center;display:flex;justify-content:flex-end}.PageHeader-breadcrumbs{display:block;margin-bottom:var(--base-size-8,.5rem);padding-bottom:var(--base-size-4,.25rem);width:100%}.PageHeader-leadingAction{margin-right:var(--base-size-4,.25rem);margin-top:2px}.PageHeader-parentLink{flex:1 1 auto}
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)}.PageHeader-contextBar,.PageHeader-titleBar{align-items:center;display:flex;flex-flow:row;justify-content:flex-end}.PageHeader-titleBar{margin-bottom:var(--space-xsmall,.25rem)}.PageHeader-title{flex:1 1 auto;font-size:var(--text-title-size-medium,1.25rem);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{align-items:center;display:flex;justify-content:flex-end}@media (max-width:543.98px){.PageHeader--singleAction .PageHeader-action{display:flex!important;position:absolute;top:10px}}.PageHeader-breadcrumbs{display:block;margin-bottom:var(--base-size-8,.5rem);padding-bottom:var(--base-size-4,.25rem);width:100%}.PageHeader-leadingAction{margin-right:var(--base-size-4,.25rem);margin-top:2px}.PageHeader-parentLink{flex:1 1 auto}
@@ -8,6 +8,7 @@
8
8
  ".PageHeader-title--large",
9
9
  ".PageHeader-description",
10
10
  ".PageHeader-actions",
11
+ ".PageHeader--singleAction .PageHeader-action",
11
12
  ".PageHeader-breadcrumbs",
12
13
  ".PageHeader-leadingAction",
13
14
  ".PageHeader-parentLink"
@@ -1 +1 @@
1
- {"version":3,"sources":["page_header.pcss"],"names":[],"mappings":"AAEA,YAIE,gHAAqE,CAHrE,YAAa,CAIb,gBAAiB,CAFjB,0CAAsC,CADtC,mDAIF,CASA,4CAHE,kBAAmB,CAHnB,YAAa,CACb,aAAc,CACd,wBAUF,CANA,qBAKE,wCACF,CAEA,kBAGE,aAAc,CAFd,+CAAwC,CACxC,8CAEF,CAEA,yBACE,2CACF,CAGA,wBAEE,gDAA2B,CAC3B,WAAY,CAFZ,8CAGF,CAEA,oBAGE,kBAAmB,CADnB,YAAa,CADb,wBAGF,CAEA,wBACE,aAAc,CAEd,sCAAiC,CACjC,wCAAkC,CAFlC,UAGF,CAEA,0BAEE,sCAAgC,CADhC,cAEF,CAEA,uBACE,aACF","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\n.PageHeader-contextBar {\n display: flex;\n flex-flow: row;\n justify-content: flex-end;\n align-items: center;\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 margin-bottom: var(--space-xsmall);\n}\n\n.PageHeader-title {\n font-size: var(--text-title-size-medium);\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.PageHeader-actions {\n justify-content: flex-end;\n display: flex;\n align-items: center;\n}\n\n.PageHeader-breadcrumbs {\n display: block;\n width: 100%;\n margin-bottom: var(--base-size-8);\n padding-bottom: var(--base-size-4);\n}\n\n.PageHeader-leadingAction {\n margin-top: 2px; /* to center align with label */\n margin-right: var(--base-size-4);\n}\n\n.PageHeader-parentLink {\n flex: 1 1 auto;\n}\n"]}
1
+ {"version":3,"sources":["page_header.pcss"],"names":[],"mappings":"AAEA,YAIE,gHAAqE,CAHrE,YAAa,CAIb,gBAAiB,CAFjB,0CAAsC,CADtC,mDAIF,CASA,4CAHE,kBAAmB,CAHnB,YAAa,CACb,aAAc,CACd,wBAUF,CANA,qBAKE,wCACF,CAEA,kBAGE,aAAc,CAFd,+CAAwC,CACxC,8CAEF,CAEA,yBACE,2CACF,CAGA,wBAEE,gDAA2B,CAC3B,WAAY,CAFZ,8CAGF,CAEA,oBAGE,kBAAmB,CADnB,YAAa,CADb,wBAGF,CAGE,4BADF,6CAMI,sBAAwB,CAJxB,iBAAkB,CAClB,QAKJ,CADE,CAGF,wBACE,aAAc,CAEd,sCAAiC,CACjC,wCAAkC,CAFlC,UAGF,CAEA,0BAEE,sCAAgC,CADhC,cAEF,CAEA,uBACE,aACF","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\n.PageHeader-contextBar {\n display: flex;\n flex-flow: row;\n justify-content: flex-end;\n align-items: center;\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 margin-bottom: var(--space-xsmall);\n}\n\n.PageHeader-title {\n font-size: var(--text-title-size-medium);\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.PageHeader-actions {\n justify-content: flex-end;\n display: flex;\n align-items: center;\n}\n\n.PageHeader--singleAction .PageHeader-action {\n @media (max-width: 543.98px) {\n position: absolute;\n top: 10px;\n\n /* Normally, the actions are hidden on mobile, except for this special case of a single action */\n display: flex !important;\n }\n}\n\n.PageHeader-breadcrumbs {\n display: block;\n width: 100%;\n margin-bottom: var(--base-size-8);\n padding-bottom: var(--base-size-4);\n}\n\n.PageHeader-leadingAction {\n margin-top: 2px; /* to center align with label */\n margin-right: var(--base-size-4);\n}\n\n.PageHeader-parentLink {\n flex: 1 1 auto;\n}\n"]}
@@ -1,13 +1,12 @@
1
1
  <%= render Primer::BaseComponent.new(**@system_arguments) do %>
2
- <% if parent_link || breadcrumbs || context_bar_actions %>
2
+ <% if @parent_link || breadcrumbs || actions.any? %>
3
3
  <div class="PageHeader-contextBar">
4
- <%= parent_link %>
4
+ <%= @parent_link %>
5
5
  <%= breadcrumbs %>
6
- <% if context_bar_actions.any? %>
7
- <%= render Primer::BaseComponent.new(tag: :div, classes: 'PageHeader-contextBarActions', display: DEFAULT_CONTEXT_BAR_ACTIONS_DISPLAY, align_items: :center) do %>
8
- <% context_bar_actions.each do |action| %>
9
- <%= action %>
10
- <% end %>
6
+ <% if render_mobile_menu? %>
7
+ <%= render(@mobile_action_menu) do |menu| %>
8
+ <% menu.with_show_button(icon: :"kebab-horizontal", "aria-label": @mobile_menu_label) %>
9
+ <% @desktop_menu_block.call(menu) unless @desktop_menu_block.nil? %>
11
10
  <% end %>
12
11
  <% end %>
13
12
  </div>
@@ -46,6 +46,16 @@
46
46
  align-items: center;
47
47
  }
48
48
 
49
+ .PageHeader--singleAction .PageHeader-action {
50
+ @media (max-width: 543.98px) {
51
+ position: absolute;
52
+ top: 10px;
53
+
54
+ /* Normally, the actions are hidden on mobile, except for this special case of a single action */
55
+ display: flex !important;
56
+ }
57
+ }
58
+
49
59
  .PageHeader-breadcrumbs {
50
60
  display: block;
51
61
  width: 100%;
@@ -20,10 +20,12 @@ module Primer
20
20
  "triangle-left"
21
21
  ].freeze
22
22
 
23
+ DEFAULT_ACTION_SCHEME = :default
24
+ MORE_MENU_DISPLAY = [:flex, :none].freeze
25
+
23
26
  DEFAULT_LEADING_ACTION_DISPLAY = [:none, :flex].freeze
24
27
  DEFAULT_BREADCRUMBS_DISPLAY = [:none, :flex].freeze
25
28
  DEFAULT_PARENT_LINK_DISPLAY = [:block, :none].freeze
26
- DEFAULT_CONTEXT_BAR_ACTIONS_DISPLAY = [:flex, :none].freeze
27
29
 
28
30
  status :open_project
29
31
 
@@ -54,24 +56,50 @@ module Primer
54
56
  # Actions
55
57
  #
56
58
  # @param system_arguments [Hash] <%= link_to_system_arguments_docs %>
57
- renders_many :actions, lambda { |**system_arguments|
58
- deny_tag_argument(**system_arguments)
59
- system_arguments[:tag] = :div
60
- system_arguments[:ml] ||= 2
59
+ renders_many :actions, types: {
60
+ icon_button: lambda { |icon:, mobile_icon:, label:, scheme: DEFAULT_ACTION_SCHEME, **system_arguments|
61
+ deny_tag_argument(**system_arguments)
62
+ system_arguments = set_action_arguments(system_arguments, scheme: scheme)
63
+ add_option_to_mobile_menu(system_arguments, mobile_icon, label, scheme)
61
64
 
62
- Primer::BaseComponent.new(**system_arguments)
63
- }
65
+ Primer::Beta::IconButton.new(icon: icon, "aria-label": label, **system_arguments)
66
+ },
67
+ button: lambda { |mobile_icon:, mobile_label:, scheme: DEFAULT_ACTION_SCHEME, **system_arguments|
68
+ deny_tag_argument(**system_arguments)
69
+ system_arguments = set_action_arguments(system_arguments, scheme: scheme)
70
+ add_option_to_mobile_menu(system_arguments, mobile_icon, mobile_label, scheme)
64
71
 
65
- # Context Bar Actions
66
- # By default shown on narrow screens. Can be overridden with system_argument: display
67
- #
68
- # @param system_arguments [Hash] <%= link_to_system_arguments_docs %>
69
- renders_many :context_bar_actions, lambda { |**system_arguments|
70
- deny_tag_argument(**system_arguments)
71
- system_arguments[:tag] = :div
72
- system_arguments[:ml] ||= 2
72
+ Primer::Beta::Button.new(**system_arguments)
73
+ },
74
+ link: lambda { |mobile_icon:, mobile_label:, scheme: DEFAULT_ACTION_SCHEME, **system_arguments|
75
+ deny_tag_argument(**system_arguments)
76
+ system_arguments = set_action_arguments(system_arguments, scheme: scheme)
77
+ add_option_to_mobile_menu(system_arguments, mobile_icon, mobile_label, scheme)
73
78
 
74
- Primer::BaseComponent.new(**system_arguments)
79
+ Primer::Beta::Link.new(**system_arguments)
80
+ },
81
+ # Should only be used rarely on a per-need basis
82
+ text: lambda { |**system_arguments|
83
+ system_arguments = set_action_arguments(system_arguments)
84
+
85
+ system_arguments[:color] ||= :muted
86
+
87
+ # Enforce that texts are hidden on mobile
88
+ system_arguments[:display] = [:none, :flex]
89
+
90
+ Primer::Beta::Text.new(**system_arguments)
91
+ },
92
+ menu: {
93
+ renders: lambda { |**system_arguments, &block|
94
+ deny_tag_argument(**system_arguments)
95
+ system_arguments[:menu_arguments] = set_action_arguments(system_arguments[:menu_arguments])
96
+
97
+ # Add the options individually to the mobile menu in the template
98
+ @desktop_menu_block = block
99
+
100
+ PageHeaderActionMenu.new(**system_arguments)
101
+ },
102
+ },
75
103
  }
76
104
 
77
105
  # Optional leading action prepend the title
@@ -93,21 +121,6 @@ module Primer
93
121
  Primer::Beta::IconButton.new(icon: icon, **system_arguments)
94
122
  }
95
123
 
96
- # Optional parent link in the context area
97
- # By default shown on narrow screens. Can be overridden with system_argument: display
98
- #
99
- # @param system_arguments [Hash] <%= link_to_system_arguments_docs %>
100
- renders_one :parent_link, lambda { |icon: DEFAULT_BACK_BUTTON_ICON, **system_arguments, &block|
101
- deny_tag_argument(**system_arguments)
102
- system_arguments[:icon] = fetch_or_fallback(BACK_BUTTON_ICON_OPTIONS, icon, DEFAULT_BACK_BUTTON_ICON)
103
- system_arguments[:classes] = class_names(system_arguments[:classes], "PageHeader-parentLink")
104
- system_arguments[:display] ||= DEFAULT_PARENT_LINK_DISPLAY
105
-
106
- render(Primer::Beta::Link.new(scheme: :primary, muted: true, **system_arguments)) do
107
- render(Primer::Beta::Octicon.new(icon: "arrow-left", "aria-label": "aria_label", mr: 2)) + content_tag(:span, &block)
108
- end
109
- }
110
-
111
124
  # Optional breadcrumbs above the title row
112
125
  # By default shown on wider screens. Can be overridden with system_argument: display
113
126
  #
@@ -117,6 +130,25 @@ module Primer
117
130
  system_arguments[:classes] = class_names(system_arguments[:classes], "PageHeader-breadcrumbs")
118
131
  system_arguments[:display] ||= DEFAULT_BREADCRUMBS_DISPLAY
119
132
 
133
+ # show parent link if there is a parent for current page
134
+ if items.length > 1
135
+ link_arguments = {}
136
+ parent_item = items[items.length - 2]
137
+ parsed_parent_item = anchor_tag_string?(parent_item) ? anchor_string_to_object(parent_item) : parent_item
138
+
139
+ link_arguments[:icon] = fetch_or_fallback(BACK_BUTTON_ICON_OPTIONS, DEFAULT_BACK_BUTTON_ICON)
140
+ link_arguments[:href] = parsed_parent_item[:href]
141
+ link_arguments[:classes] = class_names(link_arguments[:classes], "PageHeader-parentLink")
142
+ link_arguments[:display] ||= DEFAULT_PARENT_LINK_DISPLAY
143
+
144
+ @parent_link = render(Primer::Beta::Link.new(scheme: :primary, muted: true, **link_arguments)) do
145
+ render(Primer::Beta::Octicon.new(icon: "arrow-left",
146
+ "aria-label": I18n.t("button_back"),
147
+ mr: 2)
148
+ ) + content_tag(:span, parsed_parent_item[:text])
149
+ end
150
+ end
151
+
120
152
  render(Primer::Beta::Breadcrumbs.new(**system_arguments)) do |breadcrumbs|
121
153
  items.each do |item|
122
154
  item = anchor_string_to_object(item) if anchor_tag_string?(item)
@@ -130,23 +162,83 @@ module Primer
130
162
  end
131
163
  }
132
164
 
133
- def initialize(**system_arguments)
165
+ # @param mobile_menu_label [String] The tooltip label of the mobile menu
166
+ # @param system_arguments [Hash] <%= link_to_system_arguments_docs %>
167
+ def initialize(mobile_menu_label: I18n.t("label_more"), **system_arguments)
134
168
  @system_arguments = deny_tag_argument(**system_arguments)
169
+ @mobile_menu_label = mobile_menu_label
135
170
 
136
- @system_arguments[:tag] = :header
171
+ @system_arguments[:tag] = :"page-header"
137
172
  @system_arguments[:classes] =
138
173
  class_names(
139
174
  @system_arguments[:classes],
140
175
  "PageHeader"
141
176
  )
177
+
178
+ @mobile_action_menu = Primer::Alpha::ActionMenu.new(
179
+ display: MORE_MENU_DISPLAY,
180
+ anchor_align: :end
181
+ )
142
182
  end
143
183
 
144
184
  def render?
145
- title?
185
+ raise ArgumentError, "PageHeader needs a title and a breadcrumb. Please use the `with_title` and `with_breadcrumbs` slot" unless breadcrumbs? || Rails.env.production?
186
+ title? && breadcrumbs?
187
+ end
188
+
189
+ def before_render
190
+ @system_arguments[:classes] = class_names(
191
+ @system_arguments[:classes],
192
+ "PageHeader--singleAction": !render_mobile_menu?
193
+ )
194
+
195
+ content
196
+ end
197
+
198
+ def render_mobile_menu?
199
+ actions.count > 1
146
200
  end
147
201
 
148
202
  private
149
203
 
204
+ def set_action_arguments(system_arguments, scheme: nil)
205
+ system_arguments[:ml] ||= 2
206
+ system_arguments[:display] = [:none, :flex]
207
+ system_arguments[:scheme] = scheme unless scheme.nil?
208
+ system_arguments[:classes] = class_names(
209
+ system_arguments[:classes],
210
+ "PageHeader-action",
211
+ )
212
+
213
+ system_arguments[:id] ||= self.class.generate_id
214
+ system_arguments
215
+ end
216
+
217
+ def add_option_to_mobile_menu(system_arguments, mobile_icon, mobile_label, scheme)
218
+ unless mobile_icon.nil? || mobile_label.nil?
219
+ # In action menus, only :default and :danger are allowed
220
+ scheme = DEFAULT_ACTION_SCHEME unless scheme == :danger
221
+
222
+ with_menu_item(id: system_arguments[:id], label: mobile_label, scheme: scheme) do |c|
223
+ c.with_leading_visual_icon(icon: mobile_icon)
224
+ end
225
+ end
226
+ end
227
+
228
+ def with_menu_item(id:, **system_arguments, &block)
229
+ system_arguments = {
230
+ **system_arguments,
231
+ "data-for": id,
232
+ "data-action": "click:page-header#menuItemClick"
233
+ }
234
+
235
+ @mobile_action_menu.with_item(
236
+ value: "",
237
+ **system_arguments,
238
+ &block
239
+ )
240
+ end
241
+
150
242
  # transform anchor tag strings to {href, text} objects
151
243
  # e.g "\u003ca href=\"/admin\"\u003eAdministration\u003c/a\u003e"
152
244
  def anchor_string_to_object(html_string)
@@ -161,6 +253,32 @@ module Primer
161
253
  def anchor_tag_string?(item)
162
254
  item.is_a?(String) && item.start_with?("\u003c")
163
255
  end
256
+
257
+ # A Helper class to create ActionMenus inside the PageHeader action slot
258
+ class PageHeaderActionMenu < Primer::Component
259
+ status :open_project
260
+
261
+ # @param menu_arguments [Hash] The arguments accepted by <%= link_to_component(Primer::Alpha::ActionMenu) %>.
262
+ # @param button_arguments [Hash] The arguments accepted by <%= link_to_component(Primer::Beta::Button) %> or <%= link_to_component(Primer::Beta::IconButton) %>, depending on the value of the `icon:` argument.
263
+ def initialize(menu_arguments: {}, button_arguments: {})
264
+ @menu = Primer::Alpha::ActionMenu.new(**menu_arguments)
265
+ @button = @menu.with_show_button(icon: "triangle-down", **button_arguments)
266
+ end
267
+
268
+ def render_in(view_context, &block)
269
+ super(view_context) do
270
+ block.call(@menu, @button)
271
+ end
272
+ end
273
+
274
+ def before_render
275
+ content
276
+ end
277
+
278
+ def call
279
+ render(@menu)
280
+ end
281
+ end
164
282
  end
165
283
  end
166
284
  end
@@ -0,0 +1,9 @@
1
+ declare class PageHeaderElement extends HTMLElement {
2
+ menuItemClick(event: Event): void;
3
+ }
4
+ declare global {
5
+ interface Window {
6
+ PageHeaderElement: typeof PageHeaderElement;
7
+ }
8
+ }
9
+ export {};
@@ -0,0 +1,23 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ import { controller } from '@github/catalyst';
8
+ let PageHeaderElement = class PageHeaderElement extends HTMLElement {
9
+ menuItemClick(event) {
10
+ const currentTarget = event.currentTarget;
11
+ const id = currentTarget?.getAttribute('data-for');
12
+ if (id) {
13
+ document.getElementById(id)?.click();
14
+ }
15
+ }
16
+ };
17
+ PageHeaderElement = __decorate([
18
+ controller
19
+ ], PageHeaderElement);
20
+ if (!window.customElements.get('page-header')) {
21
+ window.PageHeaderElement = PageHeaderElement;
22
+ window.customElements.define('page-header', PageHeaderElement);
23
+ }
@@ -0,0 +1,25 @@
1
+ import {controller} from '@github/catalyst'
2
+
3
+ @controller
4
+ class PageHeaderElement extends HTMLElement {
5
+ menuItemClick(event: Event) {
6
+ const currentTarget = event.currentTarget as HTMLButtonElement
7
+
8
+ const id = currentTarget?.getAttribute('data-for')
9
+
10
+ if (id) {
11
+ document.getElementById(id)?.click()
12
+ }
13
+ }
14
+ }
15
+
16
+ declare global {
17
+ interface Window {
18
+ PageHeaderElement: typeof PageHeaderElement
19
+ }
20
+ }
21
+
22
+ if (!window.customElements.get('page-header')) {
23
+ window.PageHeaderElement = PageHeaderElement
24
+ window.customElements.define('page-header', PageHeaderElement)
25
+ }
@@ -22,3 +22,4 @@ import '../../../lib/primer/forms/primer_multi_input';
22
22
  import '../../../lib/primer/forms/primer_text_field';
23
23
  import '../../../lib/primer/forms/toggle_switch_input';
24
24
  import './alpha/action_menu/action_menu_element';
25
+ import './open_project/page_header_element';
@@ -22,3 +22,4 @@ import '../../../lib/primer/forms/primer_multi_input';
22
22
  import '../../../lib/primer/forms/primer_text_field';
23
23
  import '../../../lib/primer/forms/toggle_switch_input';
24
24
  import './alpha/action_menu/action_menu_element';
25
+ import './open_project/page_header_element';