From 2078da16b01ed7ae4073e38b4792a6733feeaa48 Mon Sep 17 00:00:00 2001 From: Joey Arhar Date: Mon, 25 Mar 2024 22:46:07 -0700 Subject: [PATCH] Allow top layer elements to be nested within popovers This allows top layer elements, including the dialog element, to be nested inside of an open popover, by not closing the popover when the new top layer element is opened. Without this patch, opening a modal dialog inside of a popover will make the page inert and make the dialog invisible. Fixes #9998. See also https://github.com/whatwg/fullscreen/pull/237. --- source | 87 ++++++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 63 insertions(+), 24 deletions(-) diff --git a/source b/source index 01b0e27957e..6bbfbb29a5f 100644 --- a/source +++ b/source @@ -61386,8 +61386,14 @@ interface HTMLDialogElement : HTMLElement {
  • Set this's previously focused element to the focused element.

  • -
  • Run hide all popovers given this's node - document.

  • +
  • Let hideUntil be the result of running topmost popover ancestor + given this, null, and false.

  • + +
  • If hideUntil is null, then set hideUntil to this's + node document.

  • + +
  • Run hide all popovers until given + hideUntil, false, and true.

  • Run the dialog focusing steps given this.

  • @@ -61449,8 +61455,14 @@ interface HTMLDialogElement : HTMLElement {
  • Set this's previously focused element to the focused element.

  • -
  • Run hide all popovers given this's node - document.

  • +
  • Let hideUntil be the result of running topmost popover ancestor + given this, null, and false.

  • + +
  • If hideUntil is null, then set hideUntil to this's + node document.

  • + +
  • Run hide all popovers until given + hideUntil, false, and true.

  • Run the dialog focusing steps given this.

  • @@ -84925,7 +84937,7 @@ dictionary DragEventInit : MouseEventInit { data-x="attr-popover">popover attribute.

  • Let ancestor be the result of running the topmost popover - ancestor algorithm given element and invoker.

  • + ancestor algorithm given element, invoker, and true.

  • If ancestor is null, then set ancestor to document.

  • @@ -85198,7 +85210,7 @@ dictionary DragEventInit : MouseEventInit { data-x="popover-showing-state">showing; otherwise false.

    -

    To hide all popovers until, given an To hide all popovers until, given an HTML element or Document endpoint, a boolean focusPreviousElement, and a boolean fireEvents:

    @@ -85290,21 +85302,17 @@ dictionary DragEventInit : MouseEventInit { happens. For example, during light-dismiss of a popover, this algorithm ensures that we close only the popovers that aren't related to the node clicked by the user.

    -

    To hide all popovers, given a Document document, run - hide all popovers until given document, - false, and false.

    - -

    To find the topmost popover ancestor, given a Node - newPopover, and an HTML element or null - invoker, perform the following steps. They return an HTML element or null.

    +

    To find the topmost popover ancestor, given a Node + newPopoverOrTopLayerElement, an HTML element or + null invoker, and a boolean isPopover, perform the following steps. They + return an HTML element or null.

    The topmost popover ancestor algorithm will return the topmost (latest in the - showing auto popover list) ancestor popover for the provided popover. Popovers can - be related to each other in several ways, creating a tree of popovers. There are two paths - through which one popover (call it the "child" popover) can have a topmost ancestor popover (call - it the "parent" popover):

    + showing auto popover list) ancestor popover for the provided popover or top layer + element. Popovers can be related to each other in several ways, creating a tree of popovers. + There are two paths through which one popover (call it the "child" popover) can have a topmost + ancestor popover (call it the "parent" popover):

    1. The popovers are nested within each other in the node tree. In this case, the descendant @@ -85322,14 +85330,45 @@ dictionary DragEventInit : MouseEventInit { containing an invoking element that points back to the containing popover), and it allows for the construction of a well-formed tree from the (possibly cyclic) graph of connections. Only auto popovers are considered.

      + +

      If the provided element is a top layer element such as a dialog which is not + showing as a popover, then topmost popover ancestor will only look in the node tree + to find the first popover.

      +
    1. +

      If isPopover is true:

      + +
        +
      1. Assert: newPopoverOrTopLayerElement is an HTML element.

      2. + +
      3. Assert: newPopoverOrTopLayerElement's popover attribute is not in the no popover state or the manual state.

      4. + +
      5. Assert: newPopoverOrTopLayerElement's popover visibility + state is not in the popover showing + state.

      6. +
      +
    2. + +
    3. +

      Otherwise:

      + +
        +
      1. Assert: invoker is null.

      2. +
      +
    4. +
    5. Let popoverPositions be an empty ordered map.

    6. Let index be 0.

    7. -
    8. Let document be newPopover's node document.

    9. +
    10. Let document be newPopoverOrTopLayerElement's node + document.

    11. For each popover of document's showing auto popover @@ -85343,8 +85382,8 @@ dictionary DragEventInit : MouseEventInit {

    -
  • Set popoverPositions[newPopover] to - index.

  • +
  • If isPopover is true, then set + popoverPositions[newPopoverOrTopLayerElement] to index.

  • Increment index by 1.

  • @@ -85372,12 +85411,12 @@ dictionary DragEventInit : MouseEventInit { -
  • Run checkAncestor given newPopover's parent node within the - flat tree.

  • +
  • Run checkAncestor given newPopoverOrTopLayerElement's parent node + within the flat tree.

  • Run checkAncestor given invoker.

  • -
  • return topmostPopoverAncestor.

  • +
  • Return topmostPopoverAncestor.

  • To find the nearest inclusive open popover given a Node