openproject-primer_view_components 0.86.1 → 0.87.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 (37) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +28 -0
  3. data/app/assets/javascripts/primer_view_components.js +1 -1
  4. data/app/assets/javascripts/primer_view_components.js.map +1 -1
  5. data/app/assets/styles/primer_view_components.css +1 -1
  6. data/app/assets/styles/primer_view_components.css.map +1 -1
  7. data/app/components/primer/alpha/action_menu/action_menu_element.js +14 -5
  8. data/app/components/primer/alpha/action_menu/action_menu_element.ts +14 -4
  9. data/app/components/primer/alpha/dropdown.css +1 -1
  10. data/app/components/primer/alpha/dropdown.css.map +1 -1
  11. data/app/components/primer/alpha/dropdown.pcss +8 -12
  12. data/app/components/primer/alpha/select_panel_element.js +11 -1
  13. data/app/components/primer/alpha/select_panel_element.ts +11 -2
  14. data/app/components/primer/open_project/filterable_tree_view.rb +6 -5
  15. data/app/components/primer/open_project/pagination.rb +33 -28
  16. data/app/components/primer/open_project/sub_header/quick_action_component.rb +32 -0
  17. data/app/components/primer/open_project/sub_header.html.erb +7 -7
  18. data/app/components/primer/open_project/sub_header.rb +31 -12
  19. data/app/components/primer/open_project/sub_header_element.js +3 -2
  20. data/app/components/primer/open_project/sub_header_element.ts +3 -2
  21. data/lib/primer/view_components/version.rb +2 -2
  22. data/previews/primer/alpha/dropdown_preview.rb +12 -0
  23. data/previews/primer/alpha/select_panel_preview/with_dynamic_label.html.erb +1 -1
  24. data/previews/primer/alpha/select_panel_preview/with_dynamic_label_and_aria_prefix.html.erb +1 -1
  25. data/previews/primer/alpha/select_panel_preview.rb +14 -4
  26. data/previews/primer/open_project/filterable_tree_view_preview/custom_no_results_text.html.erb +1 -1
  27. data/previews/primer/open_project/pagination_preview.rb +5 -0
  28. data/previews/primer/open_project/sub_header_preview/playground.html.erb +31 -0
  29. data/previews/primer/open_project/sub_header_preview/quick_filters.html.erb +15 -0
  30. data/previews/primer/open_project/sub_header_preview.rb +10 -17
  31. data/static/arguments.json +9 -0
  32. data/static/audited_at.json +1 -0
  33. data/static/constants.json +6 -0
  34. data/static/info_arch.json +25 -6
  35. data/static/previews.json +6 -6
  36. data/static/statuses.json +1 -0
  37. metadata +3 -1
@@ -469,6 +469,7 @@ _ActionMenuElement_handleItemActivated = function _ActionMenuElement_handleItemA
469
469
  else {
470
470
  // multi-select mode allows unchecking a checked item
471
471
  item.setAttribute('aria-checked', `${checked}`);
472
+ __classPrivateFieldGet(this, _ActionMenuElement_instances, "m", _ActionMenuElement_setDynamicLabel).call(this);
472
473
  }
473
474
  __classPrivateFieldGet(this, _ActionMenuElement_instances, "m", _ActionMenuElement_updateInput).call(this);
474
475
  this.dispatchEvent(new CustomEvent('itemActivated', {
@@ -498,21 +499,29 @@ _ActionMenuElement_isOpen = function _ActionMenuElement_isOpen() {
498
499
  return this.popoverElement?.matches(':popover-open');
499
500
  };
500
501
  _ActionMenuElement_setDynamicLabel = function _ActionMenuElement_setDynamicLabel() {
501
- if (this.selectVariant !== 'single')
502
- return;
503
502
  if (!this.dynamicLabel)
504
503
  return;
505
504
  const invokerLabel = this.invokerLabel;
506
505
  if (!invokerLabel)
507
506
  return;
508
507
  __classPrivateFieldSet(this, _ActionMenuElement_originalLabel, __classPrivateFieldGet(this, _ActionMenuElement_originalLabel, "f") || (invokerLabel.textContent || ''), "f");
509
- const itemLabel = this.querySelector('[aria-checked=true] .ActionListItem-label');
508
+ let itemLabel;
509
+ if (this.selectVariant === 'single') {
510
+ itemLabel = this.querySelector('[aria-checked=true] .ActionListItem-label')?.textContent?.trim();
511
+ }
512
+ else if (this.selectVariant === 'multiple') {
513
+ itemLabel = Array.from(this.querySelectorAll(`[aria-checked=true] .ActionListItem-label`))
514
+ .map(label => (label.textContent || '').trim())
515
+ .filter(Boolean)
516
+ .join(', ');
517
+ }
518
+ itemLabel || (itemLabel = __classPrivateFieldGet(this, _ActionMenuElement_originalLabel, "f"));
510
519
  if (itemLabel && this.dynamicLabel) {
511
520
  const prefixSpan = document.createElement('span');
512
521
  prefixSpan.classList.add('color-fg-muted');
513
522
  const contentSpan = document.createElement('span');
514
- prefixSpan.textContent = this.dynamicLabelPrefix;
515
- contentSpan.textContent = itemLabel.textContent || '';
523
+ prefixSpan.textContent = this.dynamicLabelPrefix ? `${this.dynamicLabelPrefix} ` : '';
524
+ contentSpan.textContent = itemLabel;
516
525
  invokerLabel.replaceChildren(prefixSpan, contentSpan);
517
526
  }
518
527
  else {
@@ -455,6 +455,8 @@ export class ActionMenuElement extends HTMLElement {
455
455
  } else {
456
456
  // multi-select mode allows unchecking a checked item
457
457
  item.setAttribute('aria-checked', `${checked}`)
458
+
459
+ this.#setDynamicLabel()
458
460
  }
459
461
 
460
462
  this.#updateInput()
@@ -497,18 +499,26 @@ export class ActionMenuElement extends HTMLElement {
497
499
  }
498
500
 
499
501
  #setDynamicLabel() {
500
- if (this.selectVariant !== 'single') return
501
502
  if (!this.dynamicLabel) return
502
503
  const invokerLabel = this.invokerLabel
503
504
  if (!invokerLabel) return
504
505
  this.#originalLabel ||= invokerLabel.textContent || ''
505
- const itemLabel = this.querySelector('[aria-checked=true] .ActionListItem-label')
506
+ let itemLabel: string | undefined
507
+ if (this.selectVariant === 'single') {
508
+ itemLabel = this.querySelector('[aria-checked=true] .ActionListItem-label')?.textContent?.trim()
509
+ } else if (this.selectVariant === 'multiple') {
510
+ itemLabel = Array.from(this.querySelectorAll(`[aria-checked=true] .ActionListItem-label`))
511
+ .map(label => (label.textContent || '').trim())
512
+ .filter(Boolean)
513
+ .join(', ')
514
+ }
515
+ itemLabel ||= this.#originalLabel
506
516
  if (itemLabel && this.dynamicLabel) {
507
517
  const prefixSpan = document.createElement('span')
508
518
  prefixSpan.classList.add('color-fg-muted')
509
519
  const contentSpan = document.createElement('span')
510
- prefixSpan.textContent = this.dynamicLabelPrefix
511
- contentSpan.textContent = itemLabel.textContent || ''
520
+ prefixSpan.textContent = this.dynamicLabelPrefix ? `${this.dynamicLabelPrefix} ` : ''
521
+ contentSpan.textContent = itemLabel
512
522
  invokerLabel.replaceChildren(prefixSpan, contentSpan)
513
523
  } else {
514
524
  invokerLabel.textContent = this.#originalLabel
@@ -1 +1 @@
1
- .dropdown{position:relative}.dropdown-caret{border-bottom-color:#0000;border-left-color:#0000;border-right-color:#0000;border-style:solid;border-width:var(--borderWidth-thicker) var(--borderWidth-thicker) 0;content:"";display:inline-block;height:0;vertical-align:middle;width:0}.dropdown-menu{background-clip:padding-box;background-color:var(--overlay-bgColor);border:var(--borderWidth-thin) solid var(--borderColor-default);border-radius:var(--borderRadius-medium);box-shadow:var(--shadow-floating-legacy,var(--color-shadow-large));left:0;list-style:none;margin-top:var(--base-size-2);padding-bottom:var(--control-small-paddingBlock);padding-top:var(--control-small-paddingBlock);position:absolute;top:100%;width:160px;z-index:100}.dropdown-menu:after,.dropdown-menu:before{content:"";display:inline-block;position:absolute}.dropdown-menu:before{border:8px solid #0000;border-bottom:8px solid var(--borderColor-default)}.dropdown-menu:after{border:7px solid #0000;border-bottom:7px solid var(--overlay-bgColor)}.dropdown-menu>ul{list-style:none}.dropdown-menu-no-overflow{width:auto}.dropdown-menu-no-overflow .dropdown-item{overflow:visible;padding:var(--control-small-paddingBlock) var(--control-medium-paddingInline-spacious);text-overflow:inherit}.dropdown-item{color:var(--fgColor-default);display:block;overflow:hidden;padding:var(--control-small-paddingBlock) var(--control-medium-paddingInline-condensed) var(--control-small-paddingBlock) var(--control-medium-paddingInline-spacious);text-overflow:ellipsis;white-space:nowrap}.dropdown-item:hover{background-color:var(--bgColor-accent-emphasis);color:var(--fgColor-onEmphasis);-webkit-text-decoration:none;text-decoration:none}.dropdown-item:hover>.octicon{color:inherit;opacity:1}.dropdown-item:hover [class*=color-fg-]{color:inherit!important}.dropdown-item:hover>.Label{border-color:currentcolor;color:inherit!important}.dropdown-item.btn-link,.dropdown-signout{text-align:left;width:100%}.dropdown-signout{background:none;border:0}.dropdown-divider{border-top:var(--borderWidth-thin) solid var(--borderColor-default);display:block;height:0;margin:var(--stack-gap-condensed) 0}.dropdown-header{color:var(--fgColor-muted);font-size:var(--text-body-size-small);padding:var(--control-small-paddingBlock) var(--control-medium-paddingInline-spacious)}.dropdown-item[aria-checked=false] .octicon-check{display:none}.dropdown-menu-w{left:auto;margin-right:var(--base-size-8);margin-top:0;right:100%;top:0;width:auto}.dropdown-menu-w:before{border-color:#0000;border-left-color:var(--borderColor-default);left:auto;right:-16px;top:10px}.dropdown-menu-w:after{border-color:#0000;border-left-color:var(--overlay-bgColor);left:auto;right:-14px;top:var(--base-size-12)}.dropdown-menu-e{left:100%;margin-left:var(--base-size-8);margin-top:0;top:0;width:auto}.dropdown-menu-e:before{border-color:#0000;border-right-color:var(--borderColor-default);left:-16px;top:10px}.dropdown-menu-e:after{border-color:#0000;border-right-color:var(--overlay-bgColor);left:-14px;top:var(--base-size-12)}.dropdown-menu-ne{bottom:100%;left:0;margin-bottom:var(--base-size-4);top:auto}.dropdown-menu-ne:after,.dropdown-menu-ne:before{right:auto;top:auto}.dropdown-menu-ne:before{border-bottom:0;border-left:8px solid #0000;border-right:8px solid #0000;border-top:8px solid var(--borderColor-default);bottom:-8px;left:var(--base-size-8)}.dropdown-menu-ne:after{border-bottom:0;border-left:7px solid #0000;border-right:7px solid #0000;border-top:7px solid var(--overlay-bgColor);bottom:-7px;left:10px}.dropdown-menu-s{left:auto;right:50%;transform:translateX(50%)}.dropdown-menu-s:before{right:50%;top:-16px;transform:translateX(50%)}.dropdown-menu-s:after{right:50%;top:-14px;transform:translateX(50%)}.dropdown-menu-sw{left:auto;right:0}.dropdown-menu-sw:before{left:auto;right:var(--base-size-8);top:-16px}.dropdown-menu-sw:after{left:auto;right:10px;top:-14px}.dropdown-menu-se:before{left:var(--base-size-8);top:-16px}.dropdown-menu-se:after{left:10px;top:-14px}
1
+ .dropdown{position:relative}.dropdown-caret{border-bottom-color:#0000;border-left-color:#0000;border-right-color:#0000;border-style:solid;border-width:var(--borderWidth-thicker) var(--borderWidth-thicker) 0;content:"";display:inline-block;height:0;vertical-align:middle;width:0}.dropdown-menu{background-clip:padding-box;background-color:var(--overlay-bgColor);border:var(--borderWidth-thin) solid var(--borderColor-default);border-radius:var(--borderRadius-medium);box-shadow:var(--shadow-floating-small);left:0;list-style:none;margin-top:var(--base-size-2);padding-bottom:var(--control-small-paddingBlock);padding-top:var(--control-small-paddingBlock);position:absolute;top:100%;width:160px;z-index:100}.dropdown-menu:after,.dropdown-menu:before{content:"";display:inline-block;position:absolute}.dropdown-menu:before{border:8px solid #0000;border-bottom:8px solid var(--borderColor-default)}.dropdown-menu:after{border:7px solid #0000;border-bottom:7px solid var(--overlay-bgColor)}.dropdown-menu>ul{list-style:none}.dropdown-menu-no-overflow{width:auto}.dropdown-menu-no-overflow .dropdown-item{overflow:visible;padding:var(--control-small-paddingBlock) var(--control-medium-paddingInline-spacious);text-overflow:inherit}.dropdown-item{color:var(--fgColor-default);display:block;overflow:hidden;padding:var(--control-small-paddingBlock) var(--control-medium-paddingInline-condensed) var(--control-small-paddingBlock) var(--control-medium-paddingInline-spacious);text-overflow:ellipsis;white-space:nowrap}.dropdown-item:hover{background-color:var(--bgColor-accent-emphasis);color:var(--fgColor-onEmphasis);-webkit-text-decoration:none;text-decoration:none}.dropdown-item:hover>.octicon{color:inherit;opacity:1}.dropdown-item:hover [class*=color-fg-]{color:inherit!important}.dropdown-item:hover>.Label{border-color:currentcolor;color:inherit!important}.dropdown-item.btn-link,.dropdown-signout{text-align:left;width:100%}.dropdown-signout{background:none;border:0}.dropdown-divider{border-top:var(--borderWidth-thin) solid var(--borderColor-default);display:block;height:0;margin:var(--stack-gap-condensed) 0}.dropdown-header{color:var(--fgColor-muted);font-size:var(--text-body-size-small);padding:var(--control-small-paddingBlock) var(--control-medium-paddingInline-spacious)}.dropdown-item[aria-checked=false] .octicon-check{display:none}.dropdown-menu-w{left:auto;margin-right:var(--base-size-8);margin-top:0;right:100%;top:0;width:auto}.dropdown-menu-w:before{border-color:#0000;border-left-color:var(--borderColor-default);left:auto;right:-16px;top:10px}.dropdown-menu-w:after{border-color:#0000;border-left-color:var(--overlay-bgColor);left:auto;right:-14px;top:calc(var(--base-size-12) - var(--borderWidth-thin))}.dropdown-menu-e{left:100%;margin-left:var(--base-size-8);margin-top:0;top:0;width:auto}.dropdown-menu-e:before{border-color:#0000;border-right-color:var(--borderColor-default);left:-16px;top:10px}.dropdown-menu-e:after{border-color:#0000;border-right-color:var(--overlay-bgColor);left:-14px;top:calc(var(--base-size-12) - var(--borderWidth-thin))}.dropdown-menu-ne{bottom:100%;left:0;margin-bottom:var(--base-size-4);top:auto}.dropdown-menu-ne:after,.dropdown-menu-ne:before{right:auto;top:auto}.dropdown-menu-ne:before{border-bottom:0;border-left:8px solid #0000;border-right:8px solid #0000;border-top:8px solid var(--borderColor-default);bottom:-8px;left:var(--base-size-8)}.dropdown-menu-ne:after{border-bottom:0;border-left:7px solid #0000;border-right:7px solid #0000;border-top:7px solid var(--overlay-bgColor);bottom:-7px;left:calc(var(--base-size-8) + var(--borderWidth-thin))}.dropdown-menu-s{left:auto;right:50%;transform:translateX(50%)}.dropdown-menu-s:before{right:50%;top:-16px;transform:translateX(50%)}.dropdown-menu-s:after{right:50%;top:-14px;transform:translateX(50%)}.dropdown-menu-sw{left:auto;right:0}.dropdown-menu-sw:before{left:auto;right:var(--base-size-8);top:-16px}.dropdown-menu-sw:after{left:auto;right:calc(var(--base-size-8) + var(--borderWidth-thin));top:-14px}.dropdown-menu-se:before{left:var(--base-size-8);top:-16px}.dropdown-menu-se:after{left:calc(var(--base-size-8) + var(--borderWidth-thin));top:-14px}
@@ -1 +1 @@
1
- {"version":3,"sources":["dropdown.pcss"],"names":[],"mappings":"AAEA,UACE,iBACF,CAEA,gBASE,yBAAgC,CAChC,uBAA8B,CAF9B,wBAA+B,CAF/B,kBAAmB,CACnB,oEAAqE,CAFrE,UAAW,CAJX,oBAAqB,CAErB,QAAS,CACT,qBAAsB,CAFtB,OASF,CAKA,eAaE,2BAA4B,CAD5B,uCAAwC,CAExC,+DAAgE,CAChE,wCAAyC,CACzC,kEAAoE,CAbpE,MAAO,CAQP,eAAgB,CADhB,6BAA8B,CAD9B,gDAAiD,CAFjD,6CAA8C,CAN9C,iBAAkB,CAClB,QAAS,CAGT,WAAY,CADZ,WAwCF,CA1BE,2CAIE,UAAW,CADX,oBAAqB,CADrB,iBAGF,CAGA,sBAGE,sBAA+C,CAA/C,kDACF,CAGA,qBAIE,sBAA2C,CAA3C,8CACF,CAGA,kBACE,eACF,CAGF,2BACE,UAQF,CANE,0CAGE,gBAAiB,CADjB,sFAAuF,CAEvF,qBACF,CAIF,eAKE,4BAA6B,CAJ7B,aAAc,CAGd,eAAgB,CADhB,sKAAuK,CAGvK,sBAAuB,CACvB,kBA0BF,CAxBE,qBAGE,+CAAgD,CAFhD,+BAAgC,CAChC,4BAAqB,CAArB,oBAgBF,CAbE,8BACE,aAAc,CACd,SACF,CAEA,wCACE,uBACF,CAEA,4BAEE,yBAA0B,CAD1B,uBAEF,CASJ,0CAJI,eAAgB,CADhB,UAUJ,CALA,kBAGE,eAAgB,CAChB,QACF,CAEA,kBAKE,mEAAoE,CAJpE,aAAc,CACd,QAAS,CAET,mCAEF,CAEA,iBAIE,0BAA2B,CAD3B,qCAAsC,CADtC,sFAGF,CAEA,kDACE,YACF,CAOA,iBAGE,SAAU,CAGV,+BAAgC,CADhC,YAAa,CAHb,UAAW,CADX,KAAM,CAGN,UAuBF,CAnBE,wBAME,kBAAyB,CACzB,4CAA6C,CAF7C,SAAU,CADV,WAAY,CAFZ,QAMF,CAEA,uBAKE,kBAAyB,CAEzB,wCAAyC,CAHzC,SAAU,CADV,WAAY,CAFZ,uBAOF,CAGF,iBAEE,SAAU,CAGV,8BAA+B,CAD/B,YAAa,CAHb,KAAM,CAEN,UAqBF,CAjBE,wBAKE,kBAAyB,CACzB,6CAA8C,CAF9C,UAAW,CAFX,QAKF,CAEA,uBAIE,kBAAyB,CAEzB,yCAA0C,CAH1C,UAAW,CAFX,uBAMF,CAGF,kBAEE,WAAY,CACZ,MAAO,CACP,gCAAiC,CAHjC,QAqCF,CAhCE,iDAGE,UAAW,CADX,QAEF,CAEA,yBAQE,eAAgB,CAEhB,2BAAkC,CAHlC,4BAAmC,CAFnC,+CAAgD,CAHhD,WAAY,CACZ,uBAQF,CAEA,wBASE,eAAgB,CAEhB,2BAAkC,CAHlC,4BAAmC,CAFnC,2CAA4C,CAJ5C,WAAY,CAEZ,SAQF,CAGF,iBAEE,SAAU,CADV,SAAU,CAEV,yBAeF,CAbE,wBAGE,SAAU,CADV,SAAU,CAEV,yBACF,CAEA,uBAGE,SAAU,CADV,SAAU,CAEV,yBACF,CAGF,kBAEE,SAAU,CADV,OAiBF,CAdE,yBAIE,SAAU,CADV,wBAAyB,CADzB,SAGF,CAEA,wBAKE,SAAU,CADV,UAAW,CAFX,SAIF,CAIA,yBAGE,uBAAwB,CADxB,SAEF,CAEA,wBAIE,SAAU,CAFV,SAGF","file":"dropdown.css","sourcesContent":["/* dropdown */\n\n.dropdown {\n position: relative;\n}\n\n.dropdown-caret {\n display: inline-block;\n width: 0;\n height: 0;\n vertical-align: middle;\n content: '';\n border-style: solid;\n border-width: var(--borderWidth-thicker) var(--borderWidth-thicker) 0;\n border-right-color: transparent;\n border-bottom-color: transparent;\n border-left-color: transparent;\n}\n\n/* Requires a positioning class (e.g., `.dropdown-menu-w`) to determine which\n** way the menu should render from the element triggering it. */\n\n.dropdown-menu {\n position: absolute;\n top: 100%;\n left: 0;\n z-index: 100;\n width: 160px;\n /* stylelint-disable-next-line primer/spacing */\n padding-top: var(--control-small-paddingBlock);\n /* stylelint-disable-next-line primer/spacing */\n padding-bottom: var(--control-small-paddingBlock);\n margin-top: var(--base-size-2);\n list-style: none;\n background-color: var(--overlay-bgColor);\n background-clip: padding-box;\n border: var(--borderWidth-thin) solid var(--borderColor-default);\n border-radius: var(--borderRadius-medium);\n box-shadow: var(--shadow-floating-legacy, var(--color-shadow-large));\n\n &::before,\n &::after {\n position: absolute;\n display: inline-block;\n content: '';\n }\n\n /* caret border */\n &::before {\n /* stylelint-disable-next-line primer/borders */\n border: 8px solid transparent;\n border-bottom-color: var(--borderColor-default);\n }\n\n /* caret background (should match dropdown background) */\n &::after {\n /* stylelint-disable-next-line primer/borders */\n border: 7px solid transparent;\n /* stylelint-disable-next-line primer/colors */\n border-bottom-color: var(--overlay-bgColor);\n }\n\n /* stylelint-disable-next-line selector-max-type */\n & > ul {\n list-style: none;\n }\n}\n\n.dropdown-menu-no-overflow {\n width: auto;\n\n & .dropdown-item {\n /* stylelint-disable-next-line primer/spacing */\n padding: var(--control-small-paddingBlock) var(--control-medium-paddingInline-spacious);\n overflow: visible;\n text-overflow: inherit;\n }\n}\n\n/* Dropdown items (can be links or buttons) */\n.dropdown-item {\n display: block;\n /* stylelint-disable-next-line primer/spacing */\n padding: var(--control-small-paddingBlock) var(--control-medium-paddingInline-condensed) var(--control-small-paddingBlock) var(--control-medium-paddingInline-spacious);\n overflow: hidden;\n color: var(--fgColor-default);\n text-overflow: ellipsis;\n white-space: nowrap;\n\n &:hover {\n color: var(--fgColor-onEmphasis);\n text-decoration: none;\n background-color: var(--bgColor-accent-emphasis);\n\n & > .octicon {\n color: inherit;\n opacity: 1;\n }\n\n & [class*='color-fg-'] {\n color: inherit !important;\n }\n\n & > .Label {\n color: inherit !important;\n border-color: currentcolor;\n }\n }\n\n &.btn-link {\n width: 100%;\n text-align: left;\n }\n}\n\n.dropdown-signout {\n width: 100%;\n text-align: left;\n background: none;\n border: 0;\n}\n\n.dropdown-divider {\n display: block;\n height: 0;\n /* stylelint-disable-next-line primer/spacing */\n margin: var(--stack-gap-condensed) 0;\n border-top: var(--borderWidth-thin) solid var(--borderColor-default);\n}\n\n.dropdown-header {\n /* stylelint-disable-next-line primer/spacing */\n padding: var(--control-small-paddingBlock) var(--control-medium-paddingInline-spacious);\n font-size: var(--text-body-size-small);\n color: var(--fgColor-muted);\n}\n\n.dropdown-item[aria-checked='false'] .octicon-check {\n display: none;\n}\n\n/* Directional classes\n**\n** Move the menu and the caret attached to it. Requires at least one of these on\n** the `.dropdown-menu` element. */\n\n.dropdown-menu-w {\n top: 0;\n right: 100%;\n left: auto;\n width: auto;\n margin-top: 0;\n margin-right: var(--base-size-8);\n\n &::before {\n /* stylelint-disable-next-line primer/spacing */\n top: 10px;\n /* stylelint-disable-next-line primer/spacing */\n right: -16px;\n left: auto;\n border-color: transparent;\n border-left-color: var(--borderColor-default);\n }\n\n &::after {\n top: var(--base-size-12);\n /* stylelint-disable-next-line primer/spacing */\n right: -14px;\n left: auto;\n border-color: transparent;\n /* stylelint-disable-next-line primer/colors */\n border-left-color: var(--overlay-bgColor);\n }\n}\n\n.dropdown-menu-e {\n top: 0;\n left: 100%;\n width: auto;\n margin-top: 0;\n margin-left: var(--base-size-8);\n\n &::before {\n /* stylelint-disable-next-line primer/spacing */\n top: 10px;\n /* stylelint-disable-next-line primer/spacing */\n left: -16px;\n border-color: transparent;\n border-right-color: var(--borderColor-default);\n }\n\n &::after {\n top: var(--base-size-12);\n /* stylelint-disable-next-line primer/spacing */\n left: -14px;\n border-color: transparent;\n /* stylelint-disable-next-line primer/colors */\n border-right-color: var(--overlay-bgColor);\n }\n}\n\n.dropdown-menu-ne {\n top: auto;\n bottom: 100%;\n left: 0;\n margin-bottom: var(--base-size-4);\n\n &::before,\n &::after {\n top: auto;\n right: auto;\n }\n\n &::before {\n /* stylelint-disable-next-line primer/spacing */\n bottom: -8px;\n left: var(--base-size-8);\n /* stylelint-disable-next-line primer/borders */\n border-top: 8px solid var(--borderColor-default);\n /* stylelint-disable-next-line primer/borders */\n border-right: 8px solid transparent;\n border-bottom: 0;\n /* stylelint-disable-next-line primer/borders */\n border-left: 8px solid transparent;\n }\n\n &::after {\n /* stylelint-disable-next-line primer/spacing */\n bottom: -7px;\n /* stylelint-disable-next-line primer/spacing */\n left: 10px;\n /* stylelint-disable-next-line primer/borders, primer/colors */\n border-top: 7px solid var(--overlay-bgColor);\n /* stylelint-disable-next-line primer/borders */\n border-right: 7px solid transparent;\n border-bottom: 0;\n /* stylelint-disable-next-line primer/borders */\n border-left: 7px solid transparent;\n }\n}\n\n.dropdown-menu-s {\n right: 50%;\n left: auto;\n transform: translateX(50%);\n\n &::before {\n /* stylelint-disable-next-line primer/spacing */\n top: -16px;\n right: 50%;\n transform: translateX(50%);\n }\n\n &::after {\n /* stylelint-disable-next-line primer/spacing */\n top: -14px;\n right: 50%;\n transform: translateX(50%);\n }\n}\n\n.dropdown-menu-sw {\n right: 0;\n left: auto;\n\n &::before {\n /* stylelint-disable-next-line primer/spacing */\n top: -16px;\n right: var(--base-size-8);\n left: auto;\n }\n\n &::after {\n /* stylelint-disable-next-line primer/spacing */\n top: -14px;\n /* stylelint-disable-next-line primer/spacing */\n right: 10px;\n left: auto;\n }\n}\n\n.dropdown-menu-se {\n &::before {\n /* stylelint-disable-next-line primer/spacing */\n top: -16px;\n left: var(--base-size-8);\n }\n\n &::after {\n /* stylelint-disable-next-line primer/spacing */\n top: -14px;\n /* stylelint-disable-next-line primer/spacing */\n left: 10px;\n }\n}\n"]}
1
+ {"version":3,"sources":["dropdown.pcss"],"names":[],"mappings":"AAEA,UACE,iBACF,CAEA,gBASE,yBAAgC,CAChC,uBAA8B,CAF9B,wBAA+B,CAF/B,kBAAmB,CACnB,oEAAqE,CAFrE,UAAW,CAJX,oBAAqB,CAErB,QAAS,CACT,qBAAsB,CAFtB,OASF,CAKA,eAWE,2BAA4B,CAD5B,uCAAwC,CAExC,+DAAgE,CAChE,wCAAyC,CACzC,uCAAwC,CAXxC,MAAO,CAMP,eAAgB,CADhB,6BAA8B,CAD9B,gDAAiD,CADjD,6CAA8C,CAL9C,iBAAkB,CAClB,QAAS,CAGT,WAAY,CADZ,WAsCF,CA1BE,2CAIE,UAAW,CADX,oBAAqB,CADrB,iBAGF,CAGA,sBAGE,sBAA+C,CAA/C,kDACF,CAGA,qBAIE,sBAA2C,CAA3C,8CACF,CAGA,kBACE,eACF,CAGF,2BACE,UAOF,CALE,0CAEE,gBAAiB,CADjB,sFAAuF,CAEvF,qBACF,CAIF,eAIE,4BAA6B,CAH7B,aAAc,CAEd,eAAgB,CADhB,sKAAuK,CAGvK,sBAAuB,CACvB,kBA0BF,CAxBE,qBAGE,+CAAgD,CAFhD,+BAAgC,CAChC,4BAAqB,CAArB,oBAgBF,CAbE,8BACE,aAAc,CACd,SACF,CAEA,wCACE,uBACF,CAEA,4BAEE,yBAA0B,CAD1B,uBAEF,CASJ,0CAJI,eAAgB,CADhB,UAUJ,CALA,kBAGE,eAAgB,CAChB,QACF,CAEA,kBAIE,mEAAoE,CAHpE,aAAc,CACd,QAAS,CACT,mCAEF,CAEA,iBAGE,0BAA2B,CAD3B,qCAAsC,CADtC,sFAGF,CAEA,kDACE,YACF,CAOA,iBAGE,SAAU,CAGV,+BAAgC,CADhC,YAAa,CAHb,UAAW,CADX,KAAM,CAGN,UAwBF,CApBE,wBAME,kBAAyB,CACzB,4CAA6C,CAF7C,SAAU,CADV,WAAY,CAFZ,QAMF,CAEA,uBAME,kBAAyB,CAEzB,wCAAyC,CAHzC,SAAU,CADV,WAAY,CAFZ,uDAOF,CAGF,iBAEE,SAAU,CAGV,8BAA+B,CAD/B,YAAa,CAHb,KAAM,CAEN,UAsBF,CAlBE,wBAKE,kBAAyB,CACzB,6CAA8C,CAF9C,UAAW,CAFX,QAKF,CAEA,uBAKE,kBAAyB,CAEzB,yCAA0C,CAH1C,UAAW,CAFX,uDAMF,CAGF,kBAEE,WAAY,CACZ,MAAO,CACP,gCAAiC,CAHjC,QAqCF,CAhCE,iDAGE,UAAW,CADX,QAEF,CAEA,yBAQE,eAAgB,CAEhB,2BAAkC,CAHlC,4BAAmC,CAFnC,+CAAgD,CAHhD,WAAY,CACZ,uBAQF,CAEA,wBASE,eAAgB,CAEhB,2BAAkC,CAHlC,4BAAmC,CAFnC,2CAA4C,CAJ5C,WAAY,CAEZ,uDAQF,CAGF,iBAEE,SAAU,CADV,SAAU,CAEV,yBAeF,CAbE,wBAGE,SAAU,CADV,SAAU,CAEV,yBACF,CAEA,uBAGE,SAAU,CADV,SAAU,CAEV,yBACF,CAGF,kBAEE,SAAU,CADV,OAiBF,CAdE,yBAIE,SAAU,CADV,wBAAyB,CADzB,SAGF,CAEA,wBAKE,SAAU,CADV,wDAAyD,CAFzD,SAIF,CAIA,yBAGE,uBAAwB,CADxB,SAEF,CAEA,wBAIE,uDAAwD,CAFxD,SAGF","file":"dropdown.css","sourcesContent":["/* dropdown */\n\n.dropdown {\n position: relative;\n}\n\n.dropdown-caret {\n display: inline-block;\n width: 0;\n height: 0;\n vertical-align: middle;\n content: '';\n border-style: solid;\n border-width: var(--borderWidth-thicker) var(--borderWidth-thicker) 0;\n border-right-color: transparent;\n border-bottom-color: transparent;\n border-left-color: transparent;\n}\n\n/* Requires a positioning class (e.g., `.dropdown-menu-w`) to determine which\n** way the menu should render from the element triggering it. */\n\n.dropdown-menu {\n position: absolute;\n top: 100%;\n left: 0;\n z-index: 100;\n width: 160px;\n padding-top: var(--control-small-paddingBlock);\n padding-bottom: var(--control-small-paddingBlock);\n margin-top: var(--base-size-2);\n list-style: none;\n background-color: var(--overlay-bgColor);\n background-clip: padding-box;\n border: var(--borderWidth-thin) solid var(--borderColor-default);\n border-radius: var(--borderRadius-medium);\n box-shadow: var(--shadow-floating-small);\n\n &::before,\n &::after {\n position: absolute;\n display: inline-block;\n content: '';\n }\n\n /* caret border */\n &::before {\n /* stylelint-disable-next-line primer/borders */\n border: 8px solid transparent;\n border-bottom-color: var(--borderColor-default);\n }\n\n /* caret background (should match dropdown background) */\n &::after {\n /* stylelint-disable-next-line primer/borders */\n border: 7px solid transparent;\n /* stylelint-disable-next-line primer/colors */\n border-bottom-color: var(--overlay-bgColor);\n }\n\n /* stylelint-disable-next-line selector-max-type */\n & > ul {\n list-style: none;\n }\n}\n\n.dropdown-menu-no-overflow {\n width: auto;\n\n & .dropdown-item {\n padding: var(--control-small-paddingBlock) var(--control-medium-paddingInline-spacious);\n overflow: visible;\n text-overflow: inherit;\n }\n}\n\n/* Dropdown items (can be links or buttons) */\n.dropdown-item {\n display: block;\n padding: var(--control-small-paddingBlock) var(--control-medium-paddingInline-condensed) var(--control-small-paddingBlock) var(--control-medium-paddingInline-spacious);\n overflow: hidden;\n color: var(--fgColor-default);\n text-overflow: ellipsis;\n white-space: nowrap;\n\n &:hover {\n color: var(--fgColor-onEmphasis);\n text-decoration: none;\n background-color: var(--bgColor-accent-emphasis);\n\n & > .octicon {\n color: inherit;\n opacity: 1;\n }\n\n & [class*='color-fg-'] {\n color: inherit !important;\n }\n\n & > .Label {\n color: inherit !important;\n border-color: currentcolor;\n }\n }\n\n &.btn-link {\n width: 100%;\n text-align: left;\n }\n}\n\n.dropdown-signout {\n width: 100%;\n text-align: left;\n background: none;\n border: 0;\n}\n\n.dropdown-divider {\n display: block;\n height: 0;\n margin: var(--stack-gap-condensed) 0;\n border-top: var(--borderWidth-thin) solid var(--borderColor-default);\n}\n\n.dropdown-header {\n padding: var(--control-small-paddingBlock) var(--control-medium-paddingInline-spacious);\n font-size: var(--text-body-size-small);\n color: var(--fgColor-muted);\n}\n\n.dropdown-item[aria-checked='false'] .octicon-check {\n display: none;\n}\n\n/* Directional classes\n**\n** Move the menu and the caret attached to it. Requires at least one of these on\n** the `.dropdown-menu` element. */\n\n.dropdown-menu-w {\n top: 0;\n right: 100%;\n left: auto;\n width: auto;\n margin-top: 0;\n margin-right: var(--base-size-8);\n\n &::before {\n /* stylelint-disable-next-line primer/spacing */\n top: 10px;\n /* stylelint-disable-next-line primer/spacing */\n right: -16px;\n left: auto;\n border-color: transparent;\n border-left-color: var(--borderColor-default);\n }\n\n &::after {\n /* stylelint-disable-next-line primer/spacing */\n top: calc(var(--base-size-12) - var(--borderWidth-thin));\n /* stylelint-disable-next-line primer/spacing */\n right: -14px;\n left: auto;\n border-color: transparent;\n /* stylelint-disable-next-line primer/colors */\n border-left-color: var(--overlay-bgColor);\n }\n}\n\n.dropdown-menu-e {\n top: 0;\n left: 100%;\n width: auto;\n margin-top: 0;\n margin-left: var(--base-size-8);\n\n &::before {\n /* stylelint-disable-next-line primer/spacing */\n top: 10px;\n /* stylelint-disable-next-line primer/spacing */\n left: -16px;\n border-color: transparent;\n border-right-color: var(--borderColor-default);\n }\n\n &::after {\n /* stylelint-disable-next-line primer/spacing */\n top: calc(var(--base-size-12) - var(--borderWidth-thin));\n /* stylelint-disable-next-line primer/spacing */\n left: -14px;\n border-color: transparent;\n /* stylelint-disable-next-line primer/colors */\n border-right-color: var(--overlay-bgColor);\n }\n}\n\n.dropdown-menu-ne {\n top: auto;\n bottom: 100%;\n left: 0;\n margin-bottom: var(--base-size-4);\n\n &::before,\n &::after {\n top: auto;\n right: auto;\n }\n\n &::before {\n /* stylelint-disable-next-line primer/spacing */\n bottom: -8px;\n left: var(--base-size-8);\n /* stylelint-disable-next-line primer/borders */\n border-top: 8px solid var(--borderColor-default);\n /* stylelint-disable-next-line primer/borders */\n border-right: 8px solid transparent;\n border-bottom: 0;\n /* stylelint-disable-next-line primer/borders */\n border-left: 8px solid transparent;\n }\n\n &::after {\n /* stylelint-disable-next-line primer/spacing */\n bottom: -7px;\n /* stylelint-disable-next-line primer/spacing */\n left: calc(var(--base-size-8) + var(--borderWidth-thin));\n /* stylelint-disable-next-line primer/borders, primer/colors */\n border-top: 7px solid var(--overlay-bgColor);\n /* stylelint-disable-next-line primer/borders */\n border-right: 7px solid transparent;\n border-bottom: 0;\n /* stylelint-disable-next-line primer/borders */\n border-left: 7px solid transparent;\n }\n}\n\n.dropdown-menu-s {\n right: 50%;\n left: auto;\n transform: translateX(50%);\n\n &::before {\n /* stylelint-disable-next-line primer/spacing */\n top: -16px;\n right: 50%;\n transform: translateX(50%);\n }\n\n &::after {\n /* stylelint-disable-next-line primer/spacing */\n top: -14px;\n right: 50%;\n transform: translateX(50%);\n }\n}\n\n.dropdown-menu-sw {\n right: 0;\n left: auto;\n\n &::before {\n /* stylelint-disable-next-line primer/spacing */\n top: -16px;\n right: var(--base-size-8);\n left: auto;\n }\n\n &::after {\n /* stylelint-disable-next-line primer/spacing */\n top: -14px;\n /* stylelint-disable-next-line primer/spacing */\n right: calc(var(--base-size-8) + var(--borderWidth-thin));\n left: auto;\n }\n}\n\n.dropdown-menu-se {\n &::before {\n /* stylelint-disable-next-line primer/spacing */\n top: -16px;\n left: var(--base-size-8);\n }\n\n &::after {\n /* stylelint-disable-next-line primer/spacing */\n top: -14px;\n /* stylelint-disable-next-line primer/spacing */\n left: calc(var(--base-size-8) + var(--borderWidth-thin));\n }\n}\n"]}
@@ -26,9 +26,7 @@
26
26
  left: 0;
27
27
  z-index: 100;
28
28
  width: 160px;
29
- /* stylelint-disable-next-line primer/spacing */
30
29
  padding-top: var(--control-small-paddingBlock);
31
- /* stylelint-disable-next-line primer/spacing */
32
30
  padding-bottom: var(--control-small-paddingBlock);
33
31
  margin-top: var(--base-size-2);
34
32
  list-style: none;
@@ -36,7 +34,7 @@
36
34
  background-clip: padding-box;
37
35
  border: var(--borderWidth-thin) solid var(--borderColor-default);
38
36
  border-radius: var(--borderRadius-medium);
39
- box-shadow: var(--shadow-floating-legacy, var(--color-shadow-large));
37
+ box-shadow: var(--shadow-floating-small);
40
38
 
41
39
  &::before,
42
40
  &::after {
@@ -70,7 +68,6 @@
70
68
  width: auto;
71
69
 
72
70
  & .dropdown-item {
73
- /* stylelint-disable-next-line primer/spacing */
74
71
  padding: var(--control-small-paddingBlock) var(--control-medium-paddingInline-spacious);
75
72
  overflow: visible;
76
73
  text-overflow: inherit;
@@ -80,7 +77,6 @@
80
77
  /* Dropdown items (can be links or buttons) */
81
78
  .dropdown-item {
82
79
  display: block;
83
- /* stylelint-disable-next-line primer/spacing */
84
80
  padding: var(--control-small-paddingBlock) var(--control-medium-paddingInline-condensed) var(--control-small-paddingBlock) var(--control-medium-paddingInline-spacious);
85
81
  overflow: hidden;
86
82
  color: var(--fgColor-default);
@@ -123,13 +119,11 @@
123
119
  .dropdown-divider {
124
120
  display: block;
125
121
  height: 0;
126
- /* stylelint-disable-next-line primer/spacing */
127
122
  margin: var(--stack-gap-condensed) 0;
128
123
  border-top: var(--borderWidth-thin) solid var(--borderColor-default);
129
124
  }
130
125
 
131
126
  .dropdown-header {
132
- /* stylelint-disable-next-line primer/spacing */
133
127
  padding: var(--control-small-paddingBlock) var(--control-medium-paddingInline-spacious);
134
128
  font-size: var(--text-body-size-small);
135
129
  color: var(--fgColor-muted);
@@ -163,7 +157,8 @@
163
157
  }
164
158
 
165
159
  &::after {
166
- top: var(--base-size-12);
160
+ /* stylelint-disable-next-line primer/spacing */
161
+ top: calc(var(--base-size-12) - var(--borderWidth-thin));
167
162
  /* stylelint-disable-next-line primer/spacing */
168
163
  right: -14px;
169
164
  left: auto;
@@ -190,7 +185,8 @@
190
185
  }
191
186
 
192
187
  &::after {
193
- top: var(--base-size-12);
188
+ /* stylelint-disable-next-line primer/spacing */
189
+ top: calc(var(--base-size-12) - var(--borderWidth-thin));
194
190
  /* stylelint-disable-next-line primer/spacing */
195
191
  left: -14px;
196
192
  border-color: transparent;
@@ -228,7 +224,7 @@
228
224
  /* stylelint-disable-next-line primer/spacing */
229
225
  bottom: -7px;
230
226
  /* stylelint-disable-next-line primer/spacing */
231
- left: 10px;
227
+ left: calc(var(--base-size-8) + var(--borderWidth-thin));
232
228
  /* stylelint-disable-next-line primer/borders, primer/colors */
233
229
  border-top: 7px solid var(--overlay-bgColor);
234
230
  /* stylelint-disable-next-line primer/borders */
@@ -274,7 +270,7 @@
274
270
  /* stylelint-disable-next-line primer/spacing */
275
271
  top: -14px;
276
272
  /* stylelint-disable-next-line primer/spacing */
277
- right: 10px;
273
+ right: calc(var(--base-size-8) + var(--borderWidth-thin));
278
274
  left: auto;
279
275
  }
280
276
  }
@@ -290,6 +286,6 @@
290
286
  /* stylelint-disable-next-line primer/spacing */
291
287
  top: -14px;
292
288
  /* stylelint-disable-next-line primer/spacing */
293
- left: 10px;
289
+ left: calc(var(--base-size-8) + var(--borderWidth-thin));
294
290
  }
295
291
  }
@@ -866,6 +866,7 @@ _SelectPanelElement_handleItemActivated = function _SelectPanelElement_handleIte
866
866
  else {
867
867
  __classPrivateFieldGet(this, _SelectPanelElement_instances, "m", _SelectPanelElement_removeSelectedItem).call(this, item);
868
868
  }
869
+ __classPrivateFieldGet(this, _SelectPanelElement_instances, "m", _SelectPanelElement_setDynamicLabel).call(this);
869
870
  }
870
871
  __classPrivateFieldGet(this, _SelectPanelElement_instances, "m", _SelectPanelElement_updateInput).call(this);
871
872
  __classPrivateFieldGet(this, _SelectPanelElement_instances, "m", _SelectPanelElement_updateTabIndices).call(this);
@@ -885,7 +886,16 @@ _SelectPanelElement_setDynamicLabel = function _SelectPanelElement_setDynamicLab
885
886
  if (!invokerLabel)
886
887
  return;
887
888
  __classPrivateFieldSet(this, _SelectPanelElement_originalLabel, __classPrivateFieldGet(this, _SelectPanelElement_originalLabel, "f") || (invokerLabel.textContent || ''), "f");
888
- const itemLabel = this.querySelector(`[${this.ariaSelectionType}=true] .ActionListItem-label`)?.textContent || __classPrivateFieldGet(this, _SelectPanelElement_originalLabel, "f");
889
+ let itemLabel;
890
+ if (this.selectVariant === 'single') {
891
+ itemLabel = this.querySelector(`[${this.ariaSelectionType}=true] .ActionListItem-label`)?.textContent;
892
+ }
893
+ else if (this.selectVariant === 'multiple') {
894
+ itemLabel = Array.from(this.querySelectorAll(`[${this.ariaSelectionType}=true] .ActionListItem-label`))
895
+ .map(label => label.textContent?.trim() ?? '')
896
+ .join(', ');
897
+ }
898
+ itemLabel || (itemLabel = __classPrivateFieldGet(this, _SelectPanelElement_originalLabel, "f"));
889
899
  if (itemLabel) {
890
900
  const prefixSpan = document.createElement('span');
891
901
  prefixSpan.classList.add('color-fg-muted');
@@ -916,6 +916,8 @@ export class SelectPanelElement extends HTMLElement {
916
916
  } else {
917
917
  this.#removeSelectedItem(item)
918
918
  }
919
+
920
+ this.#setDynamicLabel()
919
921
  }
920
922
 
921
923
  this.#updateInput()
@@ -952,8 +954,15 @@ export class SelectPanelElement extends HTMLElement {
952
954
  const invokerLabel = this.invokerLabel
953
955
  if (!invokerLabel) return
954
956
  this.#originalLabel ||= invokerLabel.textContent || ''
955
- const itemLabel =
956
- this.querySelector(`[${this.ariaSelectionType}=true] .ActionListItem-label`)?.textContent || this.#originalLabel
957
+ let itemLabel: string | undefined
958
+ if (this.selectVariant === 'single') {
959
+ itemLabel = this.querySelector(`[${this.ariaSelectionType}=true] .ActionListItem-label`)?.textContent
960
+ } else if (this.selectVariant === 'multiple') {
961
+ itemLabel = Array.from(this.querySelectorAll(`[${this.ariaSelectionType}=true] .ActionListItem-label`))
962
+ .map(label => label.textContent?.trim() ?? '')
963
+ .join(', ')
964
+ }
965
+ itemLabel ||= this.#originalLabel
957
966
  if (itemLabel) {
958
967
  const prefixSpan = document.createElement('span')
959
968
  prefixSpan.classList.add('color-fg-muted')
@@ -199,10 +199,10 @@ module Primer
199
199
  src: nil,
200
200
  tree_view_arguments: {},
201
201
  form_arguments: {},
202
- filter_input_arguments: DEFAULT_FILTER_INPUT_ARGUMENTS.dup,
203
- filter_mode_control_arguments: DEFAULT_FILTER_MODE_CONTROL_ARGUMENTS.dup,
204
- include_sub_items_check_box_arguments: DEFAULT_INCLUDE_SUB_ITEMS_CHECK_BOX_ARGUMENTS.dup,
205
- no_results_node_arguments: DEFAULT_NO_RESULTS_NODE_ARGUMENTS.dup,
202
+ filter_input_arguments: {},
203
+ filter_mode_control_arguments: {},
204
+ include_sub_items_check_box_arguments: {},
205
+ no_results_node_arguments: {},
206
206
  **system_arguments
207
207
  )
208
208
  @tree_view_arguments = tree_view_arguments.dup
@@ -218,6 +218,7 @@ module Primer
218
218
  **tree_view_arguments
219
219
  )
220
220
 
221
+ filter_input_arguments = filter_input_arguments.reverse_merge(DEFAULT_FILTER_INPUT_ARGUMENTS)
221
222
  filter_input_arguments[:data] = merge_data(
222
223
  filter_input_arguments, {
223
224
  data: { target: "filterable-tree-view.filterInput" }
@@ -250,7 +251,7 @@ module Primer
250
251
  @system_arguments[:tag] = :"filterable-tree-view"
251
252
  @system_arguments[:src] = src if src
252
253
 
253
- @no_results_node_arguments = no_results_node_arguments
254
+ @no_results_node_arguments = no_results_node_arguments.reverse_merge(DEFAULT_NO_RESULTS_NODE_ARGUMENTS)
254
255
  end
255
256
 
256
257
  def with_default_filter_modes
@@ -57,6 +57,10 @@ module Primer
57
57
  end
58
58
  end
59
59
 
60
+ def render?
61
+ page_count > 1
62
+ end
63
+
60
64
  private
61
65
 
62
66
  def cast_integer!(value, name)
@@ -81,36 +85,45 @@ module Primer
81
85
  end
82
86
 
83
87
  def build_pagination_model
84
- prev_page = previous_page_item
85
- next_page = next_page_item
86
-
87
- return [prev_page, next_page] unless show_pages || page_count <= 0
88
+ pages = []
88
89
 
89
- pages = if all_pages_fit?
90
- full_pagination_without_breaks
91
- else
92
- paginated_number_items
93
- end
90
+ pages << previous_page_item unless first_page?
91
+ pages.concat(number_page_items) if show_pages
92
+ pages << next_page_item unless last_page?
94
93
 
95
- [prev_page, *pages, next_page]
94
+ pages
96
95
  end
97
96
 
98
97
  def previous_page_item
99
98
  {
100
99
  type: PAGE_TYPE__PREV,
101
- num: current_page - 1,
102
- disabled: current_page == 1
100
+ num: current_page - 1
103
101
  }
104
102
  end
105
103
 
106
104
  def next_page_item
107
105
  {
108
106
  type: PAGE_TYPE__NEXT,
109
- num: current_page + 1,
110
- disabled: current_page == page_count
107
+ num: current_page + 1
111
108
  }
112
109
  end
113
110
 
111
+ def first_page?
112
+ current_page == 1
113
+ end
114
+
115
+ def last_page?
116
+ current_page == page_count
117
+ end
118
+
119
+ def number_page_items
120
+ if all_pages_fit?
121
+ full_pagination_without_breaks
122
+ else
123
+ paginated_number_items
124
+ end
125
+ end
126
+
114
127
  def full_pagination_without_breaks
115
128
  pages = []
116
129
  add_pages(pages, 1, page_count)
@@ -233,20 +246,12 @@ module Primer
233
246
  key_string = key.to_s
234
247
  content = I18n.t("pagination.#{key_string}")
235
248
 
236
- if page[:disabled]
237
- props.merge!(
238
- rel: key_string,
239
- "aria-hidden": "true",
240
- "aria-disabled": "true"
241
- )
242
- else
243
- props.merge!(
244
- rel: key_string,
245
- href: href_builder.call(page[:num]),
246
- "aria-label": I18n.t("pagination.#{key_string}_page"),
247
- **@link_arguments
248
- )
249
- end
249
+ props.merge!(
250
+ rel: key_string,
251
+ href: href_builder.call(page[:num]),
252
+ "aria-label": I18n.t("pagination.#{key_string}_page"),
253
+ **@link_arguments
254
+ )
250
255
 
251
256
  when PAGE_TYPE__NUM
252
257
  key = :"page-#{page[:num]}"
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Primer
4
+ module OpenProject
5
+ # Thin wrapper for quick filter slots that defers BaseComponent construction to render time,
6
+ # allowing system arguments (e.g. display) to be mutated in before_render.
7
+ # Do not use standalone
8
+ class SubHeader::QuickActionComponent < Primer::Component
9
+ status :open_project
10
+
11
+ def initialize(**system_arguments)
12
+ @system_arguments = system_arguments
13
+ system_arguments[:tag] = :div
14
+ system_arguments[:mr] ||= 2
15
+ system_arguments[:classes] = class_names(
16
+ "SubHeader-hiddenOnExpand",
17
+ system_arguments[:classes]
18
+ )
19
+ end
20
+
21
+ def merge_system_arguments!(**other_arguments)
22
+ @system_arguments[:aria] = merge_aria(@system_arguments, other_arguments)
23
+ @system_arguments[:data] = merge_data(@system_arguments, other_arguments)
24
+ @system_arguments.merge!(**other_arguments)
25
+ end
26
+
27
+ def call
28
+ render(Primer::BaseComponent.new(**@system_arguments)) { content }
29
+ end
30
+ end
31
+ end
32
+ end
@@ -7,15 +7,15 @@
7
7
 
8
8
  <%= render @collapsed_filter_trigger if @collapsed_filter_trigger.present? %>
9
9
 
10
- <%= render(Primer::BaseComponent.new(tag: :div, display: :flex)) do %>
11
- <% quick_filters.each do |quick_filter| %>
12
- <%= quick_filter %>
13
- <% end %>
14
-
15
- <%= render(@mobile_filter_button) if @mobile_filter_button.present? %>
16
- <%= filter_button %>
10
+ <%= quick_sort %>
11
+ <%= quick_group %>
12
+ <% quick_filters.each do |quick_filter| %>
13
+ <%= quick_filter %>
17
14
  <% end %>
18
15
 
16
+ <%= render(@mobile_filter_button) if @mobile_filter_button.present? %>
17
+ <%= filter_button %>
18
+
19
19
  <%= segmented_control %>
20
20
 
21
21
  <% if @segmented_control_block.present? %>
@@ -10,8 +10,8 @@ module Primer
10
10
  SHOWN_FILTER_TARGET_SELECTOR = "sub-header.shownItemsOnExpandedFilter"
11
11
  FILTER_EXPAND_BUTTON_TARGET_SELECTOR = "sub-header.filterExpandButton"
12
12
 
13
- MOBILE_ACTIONS_DISPLAY = [:flex, :none].freeze
14
- DESKTOP_ACTIONS_DISPLAY = [:none, :flex].freeze
13
+ MOBILE_ACTIONS_DISPLAY = [:flex, :flex, :none].freeze
14
+ DESKTOP_ACTIONS_DISPLAY = [:none, :none, :flex].freeze
15
15
 
16
16
  # A button or custom content that will render on the right-hand side of the component.
17
17
  #
@@ -101,7 +101,7 @@ module Primer
101
101
  system_arguments[:data][:action] += " input:sub-header#toggleFilterInputClearButton focus:sub-header#toggleFilterInputClearButton"
102
102
  end
103
103
 
104
- trigger_display = @collapsed_search ? :inline_flex : [:inline_flex, :none]
104
+ trigger_display = @collapsed_search ? :inline_flex : [:inline_flex, :inline_flex, :none]
105
105
 
106
106
  @collapsed_filter_trigger = Primer::Beta::IconButton.new(icon: system_arguments[:leading_visual][:icon],
107
107
  display: trigger_display,
@@ -170,16 +170,27 @@ module Primer
170
170
  }
171
171
  }
172
172
 
173
- # Quick filters shown in the left pane next to the search bar (0–5 items).
174
- # Hidden on mobile. Requires all_filters_button to be set when used.
173
+ # A slot for a generic sorting component. Will be rendered next to the search input
174
+ renders_one :quick_sort, lambda { |**kwargs|
175
+ deny_tag_argument(**kwargs)
176
+
177
+ QuickActionComponent.new(**kwargs)
178
+ }
179
+
180
+ # A slot for a generic sorting component. Will be rendered next to the sorting button
181
+ renders_one :quick_group, lambda { |**kwargs|
182
+ deny_tag_argument(**kwargs)
183
+
184
+ QuickActionComponent.new(**kwargs)
185
+ }
186
+
187
+ # Quick filters shown in the left pane next to the search bar (0–5 items total across all types).
188
+ # Hidden on smaller screens when more than one `quick_filter` is provided. Requires `filter_button` when using more than one `quick_filter`.
175
189
  # Supports ActionMenus, Buttons, IconButtons, SelectPanels, and SegmentedControls inside the block.
176
190
  renders_many :quick_filters, lambda { |**kwargs|
177
191
  deny_tag_argument(**kwargs)
178
- kwargs[:tag] = :div
179
- kwargs[:mr] ||= 2
180
- kwargs[:display] = DESKTOP_ACTIONS_DISPLAY
181
192
 
182
- Primer::BaseComponent.new(**kwargs)
193
+ QuickActionComponent.new(**kwargs)
183
194
  }
184
195
 
185
196
  renders_one :segmented_control, lambda { |**system_arguments, &block|
@@ -235,17 +246,25 @@ module Primer
235
246
  end
236
247
 
237
248
  def before_render
238
- if quick_filters.any? && filter_button.nil?
249
+ all_quick_actions = [quick_sort, quick_group].compact + quick_filters
250
+
251
+ if quick_filters.size > 1 && filter_button.nil?
239
252
  raise ArgumentError, "You must provide a filter_button when using quick_filters."
240
253
  end
241
254
 
242
255
  if quick_filters.size > 5
243
- raise ArgumentError, "SubHeader supports a maximum of 5 quick_filters, got #{quick_filters.size}."
256
+ raise ArgumentError, "SubHeader supports a maximum of 5 quick_filters, got #{all_quick_actions.size}."
257
+ end
258
+
259
+ if quick_filters.size > 1
260
+ quick_filters.each do |qf|
261
+ qf.merge_system_arguments!(display: DESKTOP_ACTIONS_DISPLAY)
262
+ end
244
263
  end
245
264
 
246
265
  @system_arguments[:classes] = class_names(
247
266
  @system_arguments[:classes],
248
- "SubHeader--emptyLeftPane" => !segmented_control? && !filter_button && !filter_input && quick_filters.empty?
267
+ "SubHeader--emptyLeftPane" => !segmented_control? && !filter_button && !filter_input && all_quick_actions.empty?
249
268
  )
250
269
  end
251
270
 
@@ -24,9 +24,10 @@ let SubHeaderElement = class SubHeaderElement extends HTMLElement {
24
24
  }
25
25
  expandFilterInput() {
26
26
  for (const item of this.shownItemsOnExpandedFilter) {
27
- item.classList.remove('d-none');
27
+ item.classList.remove('d-none', 'd-sm-none');
28
28
  }
29
29
  for (const item of this.filterExpandButton) {
30
+ item.classList.remove('d-inline-flex', 'd-sm-inline-flex');
30
31
  item.classList.add('d-none');
31
32
  }
32
33
  this.classList.add('SubHeader--expandedSearch');
@@ -37,7 +38,7 @@ let SubHeaderElement = class SubHeaderElement extends HTMLElement {
37
38
  item.classList.remove('d-none');
38
39
  }
39
40
  for (const item of this.shownItemsOnExpandedFilter) {
40
- item.classList.add('d-none');
41
+ item.classList.add('d-none', 'd-sm-none');
41
42
  }
42
43
  this.classList.remove('SubHeader--expandedSearch');
43
44
  }
@@ -29,9 +29,10 @@ class SubHeaderElement extends HTMLElement {
29
29
 
30
30
  expandFilterInput() {
31
31
  for (const item of this.shownItemsOnExpandedFilter) {
32
- item.classList.remove('d-none')
32
+ item.classList.remove('d-none', 'd-sm-none')
33
33
  }
34
34
  for (const item of this.filterExpandButton) {
35
+ item.classList.remove('d-inline-flex', 'd-sm-inline-flex')
35
36
  item.classList.add('d-none')
36
37
  }
37
38
  this.classList.add('SubHeader--expandedSearch')
@@ -43,7 +44,7 @@ class SubHeaderElement extends HTMLElement {
43
44
  item.classList.remove('d-none')
44
45
  }
45
46
  for (const item of this.shownItemsOnExpandedFilter) {
46
- item.classList.add('d-none')
47
+ item.classList.add('d-none', 'd-sm-none')
47
48
  }
48
49
  this.classList.remove('SubHeader--expandedSearch')
49
50
  }
@@ -5,8 +5,8 @@ module Primer
5
5
  module ViewComponents
6
6
  module VERSION
7
7
  MAJOR = 0
8
- MINOR = 86
9
- PATCH = 1
8
+ MINOR = 87
9
+ PATCH = 0
10
10
 
11
11
  STRING = [MAJOR, MINOR, PATCH].join(".")
12
12
  end