@@ -7,15 +7,13 @@ function dialogInvokerButtonHandler(event: Event) {
77 // If the user is clicking a valid dialog trigger
88 let dialogId = button ?. getAttribute ( 'data-show-dialog-id' )
99 if ( dialogId ) {
10- event . stopPropagation ( )
1110 const dialog = document . getElementById ( dialogId )
1211 if ( dialog instanceof HTMLDialogElement ) {
1312 dialog . showModal ( )
1413 // A buttons default behaviour in some browsers it to send a pointer event
1514 // If the behaviour is allowed through the dialog will be shown but then
1615 // quickly hidden- as if it were never shown. This prevents that.
1716 event . preventDefault ( )
18- event . stopPropagation ( )
1917 }
2018 }
2119
@@ -46,6 +44,20 @@ export class DialogHelperElement extends HTMLElement {
4644 for ( const record of records ) {
4745 if ( record . target === this . dialog ) {
4846 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+ }
4961 }
5062 }
5163 } ) . observe ( this , { subtree : true , attributeFilter : [ 'open' ] } )
@@ -58,11 +70,8 @@ export class DialogHelperElement extends HTMLElement {
5870 handleEvent ( event : MouseEvent ) {
5971 const target = event . target as HTMLElement
6072 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
6675
6776 const rect = dialog . getBoundingClientRect ( )
6877 const clickWasInsideDialog =
0 commit comments