primer_view_components 0.18.0 → 0.18.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -18,7 +18,6 @@ function dialogInvokerButtonHandler(event) {
18
18
  // If the user is clicking a valid dialog trigger
19
19
  let dialogId = button === null || button === void 0 ? void 0 : button.getAttribute('data-show-dialog-id');
20
20
  if (dialogId) {
21
- event.stopPropagation();
22
21
  const dialog = document.getElementById(dialogId);
23
22
  if (dialog instanceof HTMLDialogElement) {
24
23
  dialog.showModal();
@@ -26,7 +25,6 @@ function dialogInvokerButtonHandler(event) {
26
25
  // If the behaviour is allowed through the dialog will be shown but then
27
26
  // quickly hidden- as if it were never shown. This prevents that.
28
27
  event.preventDefault();
29
- event.stopPropagation();
30
28
  }
31
29
  }
32
30
  dialogId = button.getAttribute('data-close-dialog-id') || button.getAttribute('data-submit-dialog-id');
@@ -54,6 +52,21 @@ export class DialogHelperElement extends HTMLElement {
54
52
  for (const record of records) {
55
53
  if (record.target === this.dialog) {
56
54
  this.ownerDocument.body.classList.toggle('has-modal', this.dialog.hasAttribute('open'));
55
+ // In some older browsers, such as Chrome 122, when a top layer element (such as a dialog)
56
+ // opens from within a popover, the "hide all popovers" internal algorithm runs, hiding
57
+ // any popover that is currently open, regardless of whether or not another top layer element,
58
+ // such as a <dialog> is nested inside.
59
+ // See https://github.com/whatwg/html/issues/9998.
60
+ // This is fixed by https://github.com/whatwg/html/pull/10116, but while we still support browsers that present this bug,
61
+ // we must undo the work they did to hide ancestral popovers of the dialog:
62
+ if (this.dialog.hasAttribute('open')) {
63
+ let node = this.dialog;
64
+ while (node) {
65
+ node = node.closest('[popover]:not(:popover-open)');
66
+ if (node)
67
+ node.showPopover();
68
+ }
69
+ }
57
70
  }
58
71
  }
59
72
  }).observe(this, { subtree: true, attributeFilter: ['open'] });
@@ -65,11 +78,8 @@ export class DialogHelperElement extends HTMLElement {
65
78
  handleEvent(event) {
66
79
  const target = event.target;
67
80
  const dialog = this.dialog;
68
- if (!(dialog === null || dialog === void 0 ? void 0 : dialog.open))
69
- return;
70
- // if the target is inside the dialog, but is not the dialog itself, leave
71
- // the dialog open
72
- if ((target === null || target === void 0 ? void 0 : target.closest('dialog')) === dialog && target !== dialog)
81
+ // The click target _must_ be the dialog element itself, and not elements underneath or inside.
82
+ if (target !== dialog || !(dialog === null || dialog === void 0 ? void 0 : dialog.open))
73
83
  return;
74
84
  const rect = dialog.getBoundingClientRect();
75
85
  const clickWasInsideDialog = rect.top <= event.clientY &&
@@ -7,7 +7,6 @@ function dialogInvokerButtonHandler(event: Event) {
7
7
  // If the user is clicking a valid dialog trigger
8
8
  let dialogId = button?.getAttribute('data-show-dialog-id')
9
9
  if (dialogId) {
10
- event.stopPropagation()
11
10
  const dialog = document.getElementById(dialogId)
12
11
  if (dialog instanceof HTMLDialogElement) {
13
12
  dialog.showModal()
@@ -15,7 +14,6 @@ function dialogInvokerButtonHandler(event: Event) {
15
14
  // If the behaviour is allowed through the dialog will be shown but then
16
15
  // quickly hidden- as if it were never shown. This prevents that.
17
16
  event.preventDefault()
18
- event.stopPropagation()
19
17
  }
20
18
  }
21
19
 
@@ -46,6 +44,20 @@ export class DialogHelperElement extends HTMLElement {
46
44
  for (const record of records) {
47
45
  if (record.target === this.dialog) {
48
46
  this.ownerDocument.body.classList.toggle('has-modal', this.dialog.hasAttribute('open'))
47
+ // In some older browsers, such as Chrome 122, when a top layer element (such as a dialog)
48
+ // opens from within a popover, the "hide all popovers" internal algorithm runs, hiding
49
+ // any popover that is currently open, regardless of whether or not another top layer element,
50
+ // such as a <dialog> is nested inside.
51
+ // See https://github.com/whatwg/html/issues/9998.
52
+ // This is fixed by https://github.com/whatwg/html/pull/10116, but while we still support browsers that present this bug,
53
+ // we must undo the work they did to hide ancestral popovers of the dialog:
54
+ if (this.dialog.hasAttribute('open')) {
55
+ let node: HTMLElement | null = this.dialog
56
+ while (node) {
57
+ node = node.closest('[popover]:not(:popover-open)')
58
+ if (node) node.showPopover()
59
+ }
60
+ }
49
61
  }
50
62
  }
51
63
  }).observe(this, {subtree: true, attributeFilter: ['open']})
@@ -58,11 +70,8 @@ export class DialogHelperElement extends HTMLElement {
58
70
  handleEvent(event: MouseEvent) {
59
71
  const target = event.target as HTMLElement
60
72
  const dialog = this.dialog
61
- if (!dialog?.open) return
62
-
63
- // if the target is inside the dialog, but is not the dialog itself, leave
64
- // the dialog open
65
- if (target?.closest('dialog') === dialog && target !== dialog) return
73
+ // The click target _must_ be the dialog element itself, and not elements underneath or inside.
74
+ if (target !== dialog || !dialog?.open) return
66
75
 
67
76
  const rect = dialog.getBoundingClientRect()
68
77
  const clickWasInsideDialog =
@@ -6,7 +6,7 @@ module Primer
6
6
  module VERSION
7
7
  MAJOR = 0
8
8
  MINOR = 18
9
- PATCH = 0
9
+ PATCH = 1
10
10
 
11
11
  STRING = [MAJOR, MINOR, PATCH].join(".")
12
12
  end
@@ -0,0 +1,9 @@
1
+ <%= render(Primer::Alpha::Overlay.new(title: "An overlay")) do |o| %>
2
+ <% o.with_show_button() { "Show overlay" } %>
3
+ <% o.with_body() do %>
4
+ <%= render(Primer::Alpha::Dialog.new(id: "dialog-one", title: title, position: position, subtitle: subtitle, visually_hide_title: false)) do |d| %>
5
+ <% d.with_show_button { button_text } %>
6
+ <% d.with_body { body_text} %>
7
+ <% end %>
8
+ <% end %>
9
+ <% end %>
@@ -12,3 +12,10 @@
12
12
  <% end %>
13
13
  <% end %>
14
14
  <% end %>
15
+
16
+ <div style="margin-top:2rem">
17
+ <%= render(Primer::Beta::Flash.new(scheme: :warning)) do %>
18
+ <p>Please be careful nesting dialogs! Note that in this example, opening the second dialog does not close the first.</p>
19
+ <p>Closing a dialog while opening a dialog inside, will cause both to be invisible which will lead to undesired effects!</p>
20
+ <% end %>
21
+ </div>
@@ -248,6 +248,29 @@ module Primer
248
248
  visually_hide_title: visually_hide_title
249
249
  })
250
250
  end
251
+
252
+ # @label Dialog inside Overlay
253
+ #
254
+ # @param title [String] text
255
+ # @param subtitle [String] text
256
+ # @param size [Symbol] select [small, medium, medium_portrait, large, xlarge]
257
+ # @param position [Symbol] select [center, right, left]
258
+ # @param position_narrow [Symbol] select [inherit, bottom, fullscreen, left, right]
259
+ # @param visually_hide_title [Boolean] toggle
260
+ # @param button_text [String] text
261
+ # @param body_text [String] text
262
+ def dialog_inside_overlay(title: "Test Dialog", subtitle: nil, position: :center, size: :medium, button_text: "Show Dialog", body_text: "Content", position_narrow: :fullscreen, visually_hide_title: false)
263
+ render_with_template(locals: {
264
+ title: title,
265
+ subtitle: subtitle,
266
+ position: position,
267
+ size: size,
268
+ button_text: button_text,
269
+ body_text: body_text,
270
+ position_narrow: position_narrow,
271
+ visually_hide_title: visually_hide_title
272
+ })
273
+ end
251
274
  end
252
275
  end
253
276
  end
@@ -3375,6 +3375,19 @@
3375
3375
  "color-contrast"
3376
3376
  ]
3377
3377
  }
3378
+ },
3379
+ {
3380
+ "preview_path": "primer/alpha/dialog/dialog_inside_overlay",
3381
+ "name": "dialog_inside_overlay",
3382
+ "snapshot": "false",
3383
+ "skip_rules": {
3384
+ "wont_fix": [
3385
+ "region"
3386
+ ],
3387
+ "will_fix": [
3388
+ "color-contrast"
3389
+ ]
3390
+ }
3378
3391
  }
3379
3392
  ],
3380
3393
  "subcomponents": [
data/static/previews.json CHANGED
@@ -3139,6 +3139,19 @@
3139
3139
  "color-contrast"
3140
3140
  ]
3141
3141
  }
3142
+ },
3143
+ {
3144
+ "preview_path": "primer/alpha/dialog/dialog_inside_overlay",
3145
+ "name": "dialog_inside_overlay",
3146
+ "snapshot": "false",
3147
+ "skip_rules": {
3148
+ "wont_fix": [
3149
+ "region"
3150
+ ],
3151
+ "will_fix": [
3152
+ "color-contrast"
3153
+ ]
3154
+ }
3142
3155
  }
3143
3156
  ]
3144
3157
  },
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: primer_view_components
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.18.0
4
+ version: 0.18.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - GitHub Open Source
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-01-31 00:00:00.000000000 Z
11
+ date: 2024-02-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: actionview
@@ -728,6 +728,7 @@ files:
728
728
  - previews/primer/alpha/dialog_preview/autofocus_element.html.erb
729
729
  - previews/primer/alpha/dialog_preview/body_has_scrollbar_overflow.html.erb
730
730
  - previews/primer/alpha/dialog_preview/custom_header.html.erb
731
+ - previews/primer/alpha/dialog_preview/dialog_inside_overlay.html.erb
731
732
  - previews/primer/alpha/dialog_preview/nested_dialog.html.erb
732
733
  - previews/primer/alpha/dialog_preview/scroll_container.html.erb
733
734
  - previews/primer/alpha/dialog_preview/test.html.erb