openproject-primer_view_components 0.18.1 → 0.19.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (75) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +31 -0
  3. data/app/assets/javascripts/app/components/primer/alpha/action_menu/action_menu_element.d.ts +20 -0
  4. data/app/assets/javascripts/app/components/primer/beta/nav_list.d.ts +0 -11
  5. data/app/assets/javascripts/app/components/primer/beta/nav_list_group_element.d.ts +19 -0
  6. data/app/assets/javascripts/app/components/primer/primer.d.ts +1 -0
  7. data/app/assets/javascripts/primer_view_components.js +1 -1
  8. data/app/assets/javascripts/primer_view_components.js.map +1 -1
  9. data/app/assets/styles/primer_view_components.css +1 -1
  10. data/app/assets/styles/primer_view_components.css.map +1 -1
  11. data/app/components/primer/alpha/action_list/item.rb +13 -1
  12. data/app/components/primer/alpha/action_list.css +1 -1
  13. data/app/components/primer/alpha/action_list.css.json +1 -0
  14. data/app/components/primer/alpha/action_list.css.map +1 -1
  15. data/app/components/primer/alpha/action_list.pcss +3 -1
  16. data/app/components/primer/alpha/action_list.rb +5 -4
  17. data/app/components/primer/alpha/action_menu/action_menu_element.d.ts +20 -0
  18. data/app/components/primer/alpha/action_menu/action_menu_element.js +85 -11
  19. data/app/components/primer/alpha/action_menu/action_menu_element.ts +110 -12
  20. data/app/components/primer/alpha/action_menu/group.rb +23 -0
  21. data/app/components/primer/alpha/action_menu/heading.rb +17 -0
  22. data/app/components/primer/alpha/action_menu/list.html.erb +1 -0
  23. data/app/components/primer/alpha/action_menu/list.rb +62 -51
  24. data/app/components/primer/alpha/action_menu/list_wrapper.rb +40 -0
  25. data/app/components/primer/alpha/action_menu.rb +38 -1
  26. data/app/components/primer/alpha/overlay.css +1 -1
  27. data/app/components/primer/alpha/overlay.css.json +2 -1
  28. data/app/components/primer/alpha/overlay.css.map +1 -1
  29. data/app/components/primer/alpha/overlay.pcss +6 -2
  30. data/app/components/primer/alpha/text_field.css.map +1 -1
  31. data/app/components/primer/alpha/text_field.pcss +2 -2
  32. data/app/components/primer/alpha/tool_tip.js +8 -4
  33. data/app/components/primer/alpha/tool_tip.ts +9 -4
  34. data/app/components/primer/beta/auto_complete/auto_complete.html.erb +1 -7
  35. data/app/components/primer/beta/auto_complete/item.rb +1 -1
  36. data/app/components/primer/beta/auto_complete.rb +6 -1
  37. data/app/components/primer/beta/base_button.rb +2 -3
  38. data/app/components/primer/beta/blankslate.css +1 -1
  39. data/app/components/primer/beta/blankslate.css.map +1 -1
  40. data/app/components/primer/beta/blankslate.pcss +3 -3
  41. data/app/components/primer/beta/button.css +1 -1
  42. data/app/components/primer/beta/button.css.json +9 -8
  43. data/app/components/primer/beta/button.css.map +1 -1
  44. data/app/components/primer/beta/button.pcss +15 -11
  45. data/app/components/primer/beta/nav_list/group.html.erb +7 -5
  46. data/app/components/primer/beta/nav_list/group.rb +2 -2
  47. data/app/components/primer/beta/nav_list.d.ts +0 -11
  48. data/app/components/primer/beta/nav_list.js +2 -85
  49. data/app/components/primer/beta/nav_list.ts +1 -85
  50. data/app/components/primer/beta/nav_list_group_element.d.ts +19 -0
  51. data/app/components/primer/beta/nav_list_group_element.js +108 -0
  52. data/app/components/primer/beta/nav_list_group_element.ts +97 -0
  53. data/app/components/primer/beta/relative_time.rb +4 -4
  54. data/app/components/primer/component.rb +3 -0
  55. data/app/components/primer/primer.d.ts +1 -0
  56. data/app/components/primer/primer.js +1 -0
  57. data/app/components/primer/primer.ts +1 -0
  58. data/app/lib/primer/experimental_render_helpers.rb +32 -0
  59. data/app/lib/primer/experimental_slot_helpers.rb +30 -0
  60. data/lib/primer/view_components/version.rb +2 -2
  61. data/lib/primer/yard/lookbook_pages_backend.rb +2 -2
  62. data/previews/primer/alpha/action_menu_preview.rb +73 -7
  63. data/previews/primer/alpha/dialog_preview/with_auto_complete.html.erb +8 -0
  64. data/previews/primer/alpha/dialog_preview.rb +17 -0
  65. data/previews/primer/beta/blankslate_preview/inside_flex_container.html.erb +6 -0
  66. data/previews/primer/beta/blankslate_preview.rb +3 -0
  67. data/previews/primer/beta/nav_list_preview.rb +10 -1
  68. data/static/arguments.json +92 -1
  69. data/static/audited_at.json +4 -1
  70. data/static/classes.json +3 -0
  71. data/static/constants.json +9 -0
  72. data/static/info_arch.json +256 -52
  73. data/static/previews.json +52 -0
  74. data/static/statuses.json +3 -0
  75. metadata +14 -2
@@ -12,6 +12,17 @@ type SelectedItem = {
12
12
  const validSelectors = ['[role="menuitem"]', '[role="menuitemcheckbox"]', '[role="menuitemradio"]']
13
13
  const menuItemSelectors = validSelectors.map(selector => `:not([hidden]) > ${selector}`)
14
14
 
15
+ export type ItemActivatedEvent = {
16
+ item: Element
17
+ checked: boolean
18
+ }
19
+
20
+ declare global {
21
+ interface HTMLElementEventMap {
22
+ itemActivated: CustomEvent<ItemActivatedEvent>
23
+ }
24
+ }
25
+
15
26
  @controller
16
27
  export class ActionMenuElement extends HTMLElement {
17
28
  @target
@@ -82,7 +93,7 @@ export class ActionMenuElement extends HTMLElement {
82
93
  results.push({
83
94
  label: labelEl?.textContent,
84
95
  value: selectedItem?.getAttribute('data-value'),
85
- element: selectedItem
96
+ element: selectedItem,
86
97
  })
87
98
  }
88
99
 
@@ -102,35 +113,39 @@ export class ActionMenuElement extends HTMLElement {
102
113
 
103
114
  if (this.includeFragment) {
104
115
  this.includeFragment.addEventListener('include-fragment-replaced', this, {
105
- signal
116
+ signal,
106
117
  })
107
118
  }
108
119
  }
109
120
 
121
+ disconnectedCallback() {
122
+ this.#abortController.abort()
123
+ }
124
+
110
125
  #softDisableItems() {
111
126
  const {signal} = this.#abortController
112
127
 
113
- for (const item of this.#items) {
128
+ for (const item of this.querySelectorAll(validSelectors.join(','))) {
114
129
  item.addEventListener('click', this.#potentiallyDisallowActivation.bind(this), {signal})
115
130
  item.addEventListener('keydown', this.#potentiallyDisallowActivation.bind(this), {signal})
116
131
  }
117
132
  }
118
133
 
119
- #potentiallyDisallowActivation(event: Event) {
120
- if (!this.#isActivation(event)) return
134
+ // returns true if activation was prevented
135
+ #potentiallyDisallowActivation(event: Event): boolean {
136
+ if (!this.#isActivation(event)) return false
121
137
 
122
138
  const item = (event.target as HTMLElement).closest(menuItemSelectors.join(','))
123
- if (!item) return
139
+ if (!item) return false
124
140
 
125
141
  if (item.getAttribute('aria-disabled')) {
126
142
  event.preventDefault()
127
143
  event.stopPropagation()
128
144
  event.stopImmediatePropagation()
145
+ return true
129
146
  }
130
- }
131
147
 
132
- disconnectedCallback() {
133
- this.#abortController.abort()
148
+ return false
134
149
  }
135
150
 
136
151
  #isKeyboardActivation(event: Event): boolean {
@@ -202,6 +217,8 @@ export class ActionMenuElement extends HTMLElement {
202
217
  const targetIsItem = item !== null
203
218
 
204
219
  if (targetIsItem && eventIsActivation) {
220
+ if (this.#potentiallyDisallowActivation(event)) return
221
+
205
222
  const dialogInvoker = item.closest('[data-show-dialog-id]')
206
223
 
207
224
  if (dialogInvoker) {
@@ -214,7 +231,7 @@ export class ActionMenuElement extends HTMLElement {
214
231
  }
215
232
 
216
233
  this.#activateItem(event, item)
217
- this.#handleItemActivated(event, item)
234
+ this.#handleItemActivated(item)
218
235
 
219
236
  // Pressing the space key on a button or link will cause the page to scroll unless preventDefault()
220
237
  // is called. While calling preventDefault() appears to have no effect on link navigation, it skips
@@ -263,7 +280,7 @@ export class ActionMenuElement extends HTMLElement {
263
280
  dialog.addEventListener('cancel', handleDialogClose, {signal})
264
281
  }
265
282
 
266
- #handleItemActivated(event: Event, item: Element) {
283
+ #handleItemActivated(item: Element) {
267
284
  // Hide popover after current event loop to prevent changes in focus from
268
285
  // altering the target of the event. Not doing this specifically affects
269
286
  // <a> tags. It causes the event to be sent to the currently focused element
@@ -304,6 +321,11 @@ export class ActionMenuElement extends HTMLElement {
304
321
  }
305
322
 
306
323
  this.#updateInput()
324
+ this.dispatchEvent(
325
+ new CustomEvent('itemActivated', {
326
+ detail: {item: item.parentElement, checked: this.isItemChecked(item.parentElement)},
327
+ }),
328
+ )
307
329
  }
308
330
 
309
331
  #activateItem(event: Event, item: Element) {
@@ -410,9 +432,85 @@ export class ActionMenuElement extends HTMLElement {
410
432
  return this.querySelector(menuItemSelectors.join(','))
411
433
  }
412
434
 
413
- get #items(): HTMLElement[] {
435
+ get items(): HTMLElement[] {
414
436
  return Array.from(this.querySelectorAll(menuItemSelectors.join(',')))
415
437
  }
438
+
439
+ getItemById(itemId: string): HTMLElement | null {
440
+ return this.querySelector(`li[data-item-id="${itemId}"`)
441
+ }
442
+
443
+ isItemDisabled(item: Element | null): boolean {
444
+ if (item) {
445
+ return item.classList.contains('ActionListItem--disabled')
446
+ } else {
447
+ return false
448
+ }
449
+ }
450
+
451
+ disableItem(item: Element | null) {
452
+ if (item) {
453
+ item.classList.add('ActionListItem--disabled')
454
+ item.querySelector('.ActionListContent')!.setAttribute('aria-disabled', 'true')
455
+ }
456
+ }
457
+
458
+ enableItem(item: Element | null) {
459
+ if (item) {
460
+ item.classList.remove('ActionListItem--disabled')
461
+ item.querySelector('.ActionListContent')!.removeAttribute('aria-disabled')
462
+ }
463
+ }
464
+
465
+ isItemHidden(item: Element | null): boolean {
466
+ if (item) {
467
+ return item.hasAttribute('hidden')
468
+ } else {
469
+ return false
470
+ }
471
+ }
472
+
473
+ hideItem(item: Element | null) {
474
+ if (item) {
475
+ item.setAttribute('hidden', 'hidden')
476
+ }
477
+ }
478
+
479
+ showItem(item: Element | null) {
480
+ if (item) {
481
+ item.removeAttribute('hidden')
482
+ }
483
+ }
484
+
485
+ isItemChecked(item: Element | null) {
486
+ if (item) {
487
+ return item.querySelector('.ActionListContent')!.getAttribute('aria-checked') === 'true'
488
+ } else {
489
+ return false
490
+ }
491
+ }
492
+
493
+ checkItem(item: Element | null) {
494
+ if (item && (this.selectVariant === 'single' || this.selectVariant === 'multiple')) {
495
+ const itemContent = item.querySelector('.ActionListContent')!
496
+ const ariaChecked = itemContent.getAttribute('aria-checked') === 'true'
497
+
498
+ if (!ariaChecked) {
499
+ this.#handleItemActivated(itemContent)
500
+ }
501
+ }
502
+ }
503
+
504
+ uncheckItem(item: Element | null) {
505
+ if (item && (this.selectVariant === 'single' || this.selectVariant === 'multiple')) {
506
+ const itemContent = item.querySelector('.ActionListContent')!
507
+ const ariaChecked = itemContent.getAttribute('aria-checked') === 'true'
508
+
509
+ if (ariaChecked) {
510
+ this.#handleItemActivated(itemContent)
511
+ }
512
+ }
513
+ }
416
514
  }
417
515
 
418
516
  if (!window.customElements.get('action-menu')) {
@@ -0,0 +1,23 @@
1
+ # typed: true
2
+ # frozen_string_literal: true
3
+
4
+ module Primer
5
+ module Alpha
6
+ class ActionMenu
7
+ # This component is part of <%= link_to_component(Primer::Alpha::ActionMenu) %> and should not be
8
+ # used as a standalone component.
9
+ class Group < Primer::Alpha::ActionList
10
+ # Heading text rendered above the list of items.
11
+ #
12
+ # @param system_arguments [Hash] The arguments accepted by <%= link_to_component(Primer::Alpha::ActionMenu::Heading) %>.
13
+ def with_heading(**system_arguments, &block)
14
+ super(component_klass: Primer::Alpha::ActionMenu::Heading, **system_arguments, &block)
15
+ end
16
+
17
+ def with_divider
18
+ raise "ActionMenu groups cannot have dividers"
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Primer
4
+ module Alpha
5
+ class ActionMenu
6
+ # Heading used to describe groups within an action menu.
7
+ class Heading < Primer::Alpha::ActionList::Heading
8
+ def initialize(**)
9
+ super
10
+
11
+ # Headings don't make sense in a menu context, so use div instead
12
+ @tag = :div
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1 @@
1
+ <%= render(@list) %>
@@ -1,4 +1,3 @@
1
- # typed: true
2
1
  # frozen_string_literal: true
3
2
 
4
3
  module Primer
@@ -6,72 +5,84 @@ module Primer
6
5
  class ActionMenu
7
6
  # This component is part of <%= link_to_component(Primer::Alpha::ActionMenu) %> and should not be
8
7
  # used as a standalone component.
9
- class List < Primer::Alpha::ActionList
8
+ class List < Primer::Component
10
9
  DEFAULT_ITEM_TAG = :button
11
10
  ITEM_TAG_OPTIONS = [:a, :"clipboard-copy", DEFAULT_ITEM_TAG].freeze
12
11
 
13
- # Adds a new item to the list.
14
- #
15
- # @param data [Hash] When the menu is used as a form input (see the <%= link_to_component(Primer::Alpha::ActionMenu) %> docs), the label is submitted to the server by default. However, if the `data: { value: }` or `"data-value":` attribute is provided, it will be sent to the server instead.
16
- # @param system_arguments [Hash] These arguments are forwarded to <%= link_to_component(Primer::Alpha::ActionList::Item) %>, or whatever class is passed as the `component_klass` argument.
17
- def with_item(data: {}, **system_arguments, &block)
18
- system_arguments = organize_arguments(data: data, **system_arguments)
12
+ attr_reader :items
19
13
 
20
- super(**system_arguments) do |item|
21
- evaluate_block(item, &block)
22
- end
23
- end
14
+ # @param system_arguments [Hash] The arguments accepted by <%= link_to_component(Primer::Alpha::ActionList) %>
15
+ def initialize(**system_arguments)
16
+ @items = []
17
+ @has_group = false
24
18
 
25
- # Adds an avatar item to the list. Avatar items are a convenient way to accessibly add an item with a leading avatar image.
26
- #
27
- # @param src [String] The source url of the avatar image.
28
- # @param username [String] The username associated with the avatar.
29
- # @param full_name [String] Optional. The user's full name.
30
- # @param full_name_scheme [Symbol] Optional. How to display the user's full name. <%= one_of(Primer::Alpha::ActionList::Item::DESCRIPTION_SCHEME_OPTIONS) %>
31
- # @param data [Hash] When the menu is used as a form input (see the <%= link_to_component(Primer::Alpha::ActionMenu) %> docs), the label is submitted to the server by default. However, if the `data: { value: }` or `"data-value":` attribute is provided, it will be sent to the server instead.
32
- # @param avatar_arguments [Hash] Optional. The arguments accepted by <%= link_to_component(Primer::Beta::Avatar) %>.
33
- # @param system_arguments [Hash] These arguments are forwarded to <%= link_to_component(Primer::Alpha::ActionList::Item) %>, or whatever class is passed as the `component_klass` argument.
34
- def with_avatar_item(src:, username:, full_name: nil, full_name_scheme: Primer::Alpha::ActionList::Item::DEFAULT_DESCRIPTION_SCHEME, data: {}, avatar_arguments: {}, **system_arguments, &block)
35
- system_arguments = organize_arguments(data: data, **system_arguments)
36
-
37
- super(src: src, username: username, full_name: full_name, full_name_scheme: full_name_scheme, avatar_arguments: avatar_arguments, **system_arguments) do |item|
38
- evaluate_block(item, &block)
39
- end
19
+ @list = Primer::Alpha::ActionMenu::ListWrapper.new(**system_arguments)
40
20
  end
41
21
 
42
- # @param menu_id [String] ID of the parent menu.
43
- # @param system_arguments [Hash] The arguments accepted by <%= link_to_component(Primer::Alpha::ActionList) %>
44
- def initialize(menu_id:, **system_arguments, &block)
45
- @menu_id = menu_id
22
+ def with_group(**system_arguments, &block)
23
+ @has_group = true
46
24
 
47
- system_arguments[:aria] = merge_aria(
48
- system_arguments,
49
- { aria: { labelledby: "#{@menu_id}-button" } }
50
- )
25
+ @items << {
26
+ type: :group,
27
+ kwargs: system_arguments,
28
+ block: block
29
+ }
30
+ end
51
31
 
52
- system_arguments[:role] = :menu
53
- system_arguments[:scheme] = :inset
54
- system_arguments[:id] = "#{@menu_id}-list"
32
+ def with_item(**system_arguments, &block)
33
+ @items << {
34
+ type: :item,
35
+ kwargs: organize_arguments(**system_arguments),
36
+ block: block
37
+ }
38
+ end
39
+
40
+ def with_avatar_item(**system_arguments, &block)
41
+ @items << {
42
+ type: :avatar_item,
43
+ kwargs: organize_arguments(**system_arguments),
44
+ block: block
45
+ }
46
+ end
55
47
 
56
- super(**system_arguments, &block)
48
+ def with_divider(**system_arguments, &block)
49
+ @items << {
50
+ type: :divider,
51
+ kwargs: system_arguments,
52
+ block: block
53
+ }
57
54
  end
58
55
 
59
56
  private
60
57
 
61
- def evaluate_block(*args, &block)
62
- # Prevent double renders by using the capture method on the component
63
- # that originally received the block.
64
- #
65
- # Handle blocks that originate from C code such as `&:method` by checking
66
- # source_location. Such blocks don't allow access to their receiver.
67
- return unless block&.source_location
58
+ def contains_group?
59
+ @has_group
60
+ end
68
61
 
69
- block_context = block.binding.receiver
62
+ def before_render
63
+ content
64
+
65
+ @items.each do |item|
66
+ case item[:type]
67
+ when :divider, :group
68
+ add_item(item, to: @list)
69
+ else
70
+ if contains_group?
71
+ @list.with_group do |group|
72
+ add_item(item, to: group)
73
+ end
74
+ else
75
+ add_item(item, to: @list)
76
+ end
77
+ end
78
+ end
79
+ end
70
80
 
71
- if block_context.class < ActionView::Base
72
- block_context.capture(*args, &block)
73
- else
74
- capture(*args, &block)
81
+ def add_item(item, to:)
82
+ parent = to
83
+ mtd = :"with_#{item[:type]}"
84
+ parent.send(mtd, **item[:kwargs]) do |item_instance|
85
+ evaluate_block(item_instance, &item[:block])
75
86
  end
76
87
  end
77
88
 
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Primer
4
+ module Alpha
5
+ class ActionMenu
6
+ # This component is part of <%= link_to_component(Primer::Alpha::ActionMenu) %> and should not be
7
+ # used as a standalone component.
8
+ class ListWrapper < Primer::Alpha::ActionList
9
+ add_polymorphic_slot_type(
10
+ slot_name: :items,
11
+ type: :group,
12
+ callable: lambda { |**system_arguments|
13
+ Primer::Alpha::ActionMenu::Group.new(
14
+ **system_arguments,
15
+ role: :group,
16
+ select_variant: @select_variant
17
+ )
18
+ }
19
+ )
20
+
21
+ # @param menu_id [String] ID of the parent menu.
22
+ # @param system_arguments [Hash] The arguments accepted by <%= link_to_component(Primer::Alpha::ActionList) %>
23
+ def initialize(menu_id:, **system_arguments)
24
+ @menu_id = menu_id
25
+
26
+ system_arguments[:aria] = merge_aria(
27
+ system_arguments,
28
+ { aria: { labelledby: "#{@menu_id}-button" } }
29
+ )
30
+
31
+ system_arguments[:role] = :menu
32
+ system_arguments[:scheme] = :inset
33
+ system_arguments[:id] = "#{@menu_id}-list"
34
+
35
+ super(**system_arguments)
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
@@ -128,6 +128,39 @@ module Primer
128
128
  #
129
129
  # Additional information around the keyboard functionality and implementation can be found on the
130
130
  # [WAI-ARIA Authoring Practices](https://www.w3.org/TR/wai-aria-practices-1.2/#menu).
131
+ #
132
+ # ### JavaScript API
133
+ #
134
+ # `ActionList`s render an `<action-list>` custom element that exposes behavior to the client. For all these methods,
135
+ # `itemId` refers to the value of the `item_id:` argument (see below) that is used to populate the `data-item-id` HTML
136
+ # attribute.
137
+ #
138
+ # #### Query methods
139
+ #
140
+ # * `getItemById(itemId: string): Element`: Returns the item's HTML `<li>` element. The return value can be passed as the `item` argument to the other methods listed below.
141
+ # * `isItemChecked(item: Element): boolean`: Returns `true` if the item is checked, `false` otherwise.
142
+ # * `isItemHidden(item: Element): boolean`: Returns `true` if the item is hidden, `false` otherwise.
143
+ # * `isItemDisabled(item: Element): boolean`: Returns `true` if the item is disabled, `false` otherwise.
144
+ #
145
+ # #### State methods
146
+ #
147
+ # * `showItem(item: Element)`: Shows the item, i.e. makes it visible.
148
+ # * `hideItem(item: Element)`: Hides the item, i.e. makes it invisible.
149
+ # * `enableItem(item: Element)`: Enables the item, i.e. makes it clickable by the mouse and keyboard.
150
+ # * `disableItem(item: Element)`: Disables the item, i.e. makes it unclickable by the mouse and keyboard.
151
+ # * `checkItem(item: Element)`: Checks the item. Only has an effect in single- and multi-select modes.
152
+ # * `uncheckItem(item: Element)`: Unchecks the item. Only has an effect in multi-select mode, since items cannot be unchecked in single-select mode.
153
+ #
154
+ # #### Events
155
+ #
156
+ # The `<action-menu>` element fires an `itemActivated` event whenever an item is activated (eg. clicked) via the mouse or keyboard.
157
+ #
158
+ # ```typescript
159
+ # document.querySelector("action-menu").addEventListener("itemActivated", (event: ItemActivatedEvent) => {
160
+ # event.item // Element: the <li> item that was activated
161
+ # event.checked // boolean: whether or not the result of the activation checked the item
162
+ # })
163
+ # ```
131
164
  class ActionMenu < Primer::Component
132
165
  status :alpha
133
166
 
@@ -175,7 +208,7 @@ module Primer
175
208
 
176
209
  @system_arguments[:preload] = true if @src.present? && preload?
177
210
 
178
- select_variant = fetch_or_fallback(SELECT_VARIANT_OPTIONS, select_variant, DEFAULT_SELECT_VARIANT)
211
+ @select_variant = fetch_or_fallback(SELECT_VARIANT_OPTIONS, select_variant, DEFAULT_SELECT_VARIANT)
179
212
 
180
213
  @system_arguments[:tag] = :"action-menu"
181
214
  @system_arguments[:"data-select-variant"] = select_variant
@@ -243,6 +276,10 @@ module Primer
243
276
  @list.with_avatar_item(**system_arguments, &block)
244
277
  end
245
278
 
279
+ def with_group(**system_arguments, &block)
280
+ @list.with_group(**system_arguments, &block)
281
+ end
282
+
246
283
  private
247
284
 
248
285
  def before_render
@@ -1 +1 @@
1
- anchored-position[popover]{background:none;border-width:0;min-width:192px;overflow:visible;padding:0;position:absolute}.Overlay{display:flex}anchored-position.not-anchored::backdrop{background-color:var(--overlay-backdrop-bgColor,var(--color-neutral-muted))}
1
+ anchored-position[popover]{border-width:0;min-width:192px;overflow:visible;padding:0;position:absolute}anchored-position:not(.Overlay){background:none}.Overlay[popover]:not(:popover-open){display:none}anchored-position.not-anchored::backdrop{background-color:var(--overlay-backdrop-bgColor,var(--color-neutral-muted))}
@@ -2,7 +2,8 @@
2
2
  "name": "alpha/overlay",
3
3
  "selectors": [
4
4
  "anchored-position[popover]",
5
- ".Overlay",
5
+ "anchored-position:not(.Overlay)",
6
+ ".Overlay[popover]:not(:popover-open)",
6
7
  "anchored-position.not-anchored::backdrop"
7
8
  ]
8
9
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["overlay.pcss"],"names":[],"mappings":"AAAA,2BAME,eAAgB,CALhB,cAAe,CAGf,eAAgB,CAChB,gBAAiB,CAHjB,SAAU,CACV,iBAIF,CAEA,SACE,YACF,CAEA,yCACE,2EACF","file":"overlay.css","sourcesContent":["anchored-position[popover] {\n border-width: 0;\n padding: 0;\n position: absolute;\n min-width: 192px;\n overflow: visible;\n background: none;\n}\n\n.Overlay {\n display: flex;\n}\n\nanchored-position.not-anchored::backdrop {\n background-color: var(--overlay-backdrop-bgColor, var(--color-neutral-muted));\n}\n"]}
1
+ {"version":3,"sources":["overlay.pcss"],"names":[],"mappings":"AAAA,2BACE,cAAe,CAGf,eAAgB,CAChB,gBAAiB,CAHjB,SAAU,CACV,iBAGF,CAEA,gCACE,eACF,CAGA,qCACE,YACF,CAEA,yCACE,2EACF","file":"overlay.css","sourcesContent":["anchored-position[popover] {\n border-width: 0;\n padding: 0;\n position: absolute;\n min-width: 192px;\n overflow: visible;\n}\n\nanchored-position:not(.Overlay) {\n background: none;\n}\n\n/* stylelint-disable-next-line selector-pseudo-class-no-unknown */\n.Overlay[popover]:not(:popover-open) {\n display: none\n}\n\nanchored-position.not-anchored::backdrop {\n background-color: var(--overlay-backdrop-bgColor, var(--color-neutral-muted));\n}\n"]}
@@ -4,11 +4,15 @@ anchored-position[popover] {
4
4
  position: absolute;
5
5
  min-width: 192px;
6
6
  overflow: visible;
7
+ }
8
+
9
+ anchored-position:not(.Overlay) {
7
10
  background: none;
8
11
  }
9
12
 
10
- .Overlay {
11
- display: flex;
13
+ /* stylelint-disable-next-line selector-pseudo-class-no-unknown */
14
+ .Overlay[popover]:not(:popover-open) {
15
+ display: none
12
16
  }
13
17
 
14
18
  anchored-position.not-anchored::backdrop {