-
Notifications
You must be signed in to change notification settings - Fork 2.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Only use the used invoker to establish popover hierarchy #9171
Conversation
Fixes whatwg#9160 If this patch is merged, then whatwg#9048 is obsolete and can be closed without merging. Rationale (copied from [masons patch](https://chromium-review.googlesource.com/c/chromium/src/+/4429412)): Instead of using just the DOM structure to establish the popover hierarchy, the user's behavior should matter. For example, if one popover contains a popover invoker pointing to another popover, it should matter whether that invoker is *actually used* to open the second popover. An example: - Component 1 is a third party widget, which uses popover - Component 2 is another third party widget, also using popover - A page wants to use both components separately, from separate invoking buttons. - Component 1 also wants to be able to use Component 2, via a button within Component 1. In this example, the page should be able to still independently use these components. So a user clicking the page's button for Component 2 is expected to close Component 1 if it's open, because that's a direct invocation of Component 2. However, if the user clicks the button within Component 1 to get Component 2, it is natural to leave Component 1 open because this is a nested call. Important note: this often happens to be the behavior even before this change, since the user clicking on the page-level Component 2 invoking button represents a light dismiss signal for Component 1, so it closes either way. But this patch simplifies the implementation, removing the need to track all invokers on the page, and also removing the need to continuously check whether invoker relationships have changed.
This seems like an improvement for its simplicity. I'm trying to think of cases where #9048 would still be relevant, and the only case that comes to mind is element removal (that would change the invoker to null, or be re-appended to a different popover, which would change the parent/child relationship). Applying #9048 for element removal may be too aggressive in cases where the invoker is re-appended in a way that doesn't change the parent/child relationship, so I guess this is really up to how important we think it is to always preserve hierarchy correctness. |
See [1] for more context, but the idea is that instead of using just the DOM structure to establish the popover hierarchy, the user's behavior should matter. For example, if one popover contains a popover invoker pointing to another popover, it should matter whether that invoker is *actually used* to open the second popover. An example: - Component 1 is a third party widget, which uses popover - Component 2 is another third party widget, also using popover - A page wants to use both components separately, from separate invoking buttons. - Component 1 also wants to be able to use Component 2, via a button within Component 1. In this example, the page should be able to still independently use these components. So a user clicking the page's button for Component 2 is expected to close Component 1 if it's open, because that's a direct invocation of Component 2. However, if the user clicks the button within Component 1 to get Component 2, it is natural to leave Component 1 open because this is a nested call. Important note: this often happens to be the behavior even before this CL, since the user clicking on the page-level Component 2 invoking button represents a light dismiss signal for Component 1, so it closes either way. But this CL simplifies the implementation considerably, removing the need to track all invokers on the page, and also removing the need to continuously check whether invoker relationships have changed. Spec PR: whatwg/html#9171 [1] whatwg/html#9160 Bug: 1307772 Change-Id: I60ccb133a79084db8c251218fdbd10684fea947b
Glad you think so!
Good point. Perhaps we do the #9048 "check and possibly close popover stack" check only when a new popover is being shown or hidden? Perhaps as a part of "hide all popovers until" or something? That should be the only time changes in the hierarchy really matter now, I think. |
See [1] for more context, but the idea is that instead of using just the DOM structure to establish the popover hierarchy, the user's behavior should matter. For example, if one popover contains a popover invoker pointing to another popover, it should matter whether that invoker is *actually used* to open the second popover. An example: - Component 1 is a third party widget, which uses popover - Component 2 is another third party widget, also using popover - A page wants to use both components separately, from separate invoking buttons. - Component 1 also wants to be able to use Component 2, via a button within Component 1. In this example, the page should be able to still independently use these components. So a user clicking the page's button for Component 2 is expected to close Component 1 if it's open, because that's a direct invocation of Component 2. However, if the user clicks the button within Component 1 to get Component 2, it is natural to leave Component 1 open because this is a nested call. Important note: this often happens to be the behavior even before this CL, since the user clicking on the page-level Component 2 invoking button represents a light dismiss signal for Component 1, so it closes either way. But this CL simplifies the implementation considerably, removing the need to track all invokers on the page, and also removing the need to continuously check whether invoker relationships have changed. Spec PR: whatwg/html#9171 [1] whatwg/html#9160 Bug: 1307772 Change-Id: I60ccb133a79084db8c251218fdbd10684fea947b Cq-Do-Not-Cancel-Tryjobs: true
See [1] for more context, but the idea is that instead of using just the DOM structure to establish the popover hierarchy, the user's behavior should matter. For example, if one popover contains a popover invoker pointing to another popover, it should matter whether that invoker is *actually used* to open the second popover. An example: - Component 1 is a third party widget, which uses popover - Component 2 is another third party widget, also using popover - A page wants to use both components separately, from separate invoking buttons. - Component 1 also wants to be able to use Component 2, via a button within Component 1. In this example, the page should be able to still independently use these components. So a user clicking the page's button for Component 2 is expected to close Component 1 if it's open, because that's a direct invocation of Component 2. However, if the user clicks the button within Component 1 to get Component 2, it is natural to leave Component 1 open because this is a nested call. Important note: this often happens to be the behavior even before this CL, since the user clicking on the page-level Component 2 invoking button represents a light dismiss signal for Component 1, so it closes either way. But this CL simplifies the implementation considerably, removing the need to track all invokers on the page, and also removing the need to continuously check whether invoker relationships have changed. Spec PR: whatwg/html#9171 [1] whatwg/html#9160 Bug: 1307772 Change-Id: I60ccb133a79084db8c251218fdbd10684fea947b Cq-Do-Not-Cancel-Tryjobs: true Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4429412 Commit-Queue: Mason Freed <masonf@chromium.org> Code-Coverage: Findit <findit-for-me@appspot.gserviceaccount.com> Reviewed-by: Joey Arhar <jarhar@chromium.org> Cr-Commit-Position: refs/heads/main@{#1131606}
See [1] for more context, but the idea is that instead of using just the DOM structure to establish the popover hierarchy, the user's behavior should matter. For example, if one popover contains a popover invoker pointing to another popover, it should matter whether that invoker is *actually used* to open the second popover. An example: - Component 1 is a third party widget, which uses popover - Component 2 is another third party widget, also using popover - A page wants to use both components separately, from separate invoking buttons. - Component 1 also wants to be able to use Component 2, via a button within Component 1. In this example, the page should be able to still independently use these components. So a user clicking the page's button for Component 2 is expected to close Component 1 if it's open, because that's a direct invocation of Component 2. However, if the user clicks the button within Component 1 to get Component 2, it is natural to leave Component 1 open because this is a nested call. Important note: this often happens to be the behavior even before this CL, since the user clicking on the page-level Component 2 invoking button represents a light dismiss signal for Component 1, so it closes either way. But this CL simplifies the implementation considerably, removing the need to track all invokers on the page, and also removing the need to continuously check whether invoker relationships have changed. Spec PR: whatwg/html#9171 [1] whatwg/html#9160 Bug: 1307772 Change-Id: I60ccb133a79084db8c251218fdbd10684fea947b Cq-Do-Not-Cancel-Tryjobs: true Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4429412 Commit-Queue: Mason Freed <masonf@chromium.org> Code-Coverage: Findit <findit-for-me@appspot.gserviceaccount.com> Reviewed-by: Joey Arhar <jarhar@chromium.org> Cr-Commit-Position: refs/heads/main@{#1131606}
See [1] for more context, but the idea is that instead of using just the DOM structure to establish the popover hierarchy, the user's behavior should matter. For example, if one popover contains a popover invoker pointing to another popover, it should matter whether that invoker is *actually used* to open the second popover. An example: - Component 1 is a third party widget, which uses popover - Component 2 is another third party widget, also using popover - A page wants to use both components separately, from separate invoking buttons. - Component 1 also wants to be able to use Component 2, via a button within Component 1. In this example, the page should be able to still independently use these components. So a user clicking the page's button for Component 2 is expected to close Component 1 if it's open, because that's a direct invocation of Component 2. However, if the user clicks the button within Component 1 to get Component 2, it is natural to leave Component 1 open because this is a nested call. Important note: this often happens to be the behavior even before this CL, since the user clicking on the page-level Component 2 invoking button represents a light dismiss signal for Component 1, so it closes either way. But this CL simplifies the implementation considerably, removing the need to track all invokers on the page, and also removing the need to continuously check whether invoker relationships have changed. Spec PR: whatwg/html#9171 [1] whatwg/html#9160 Bug: 1307772 Change-Id: I60ccb133a79084db8c251218fdbd10684fea947b Cq-Do-Not-Cancel-Tryjobs: true Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4429412 Commit-Queue: Mason Freed <masonf@chromium.org> Code-Coverage: Findit <findit-for-me@appspot.gserviceaccount.com> Reviewed-by: Joey Arhar <jarhar@chromium.org> Cr-Commit-Position: refs/heads/main@{#1131606}
…opover hierarchy, a=testonly Automatic update from web-platform-tests Only use the used invoker to establish popover hierarchy See [1] for more context, but the idea is that instead of using just the DOM structure to establish the popover hierarchy, the user's behavior should matter. For example, if one popover contains a popover invoker pointing to another popover, it should matter whether that invoker is *actually used* to open the second popover. An example: - Component 1 is a third party widget, which uses popover - Component 2 is another third party widget, also using popover - A page wants to use both components separately, from separate invoking buttons. - Component 1 also wants to be able to use Component 2, via a button within Component 1. In this example, the page should be able to still independently use these components. So a user clicking the page's button for Component 2 is expected to close Component 1 if it's open, because that's a direct invocation of Component 2. However, if the user clicks the button within Component 1 to get Component 2, it is natural to leave Component 1 open because this is a nested call. Important note: this often happens to be the behavior even before this CL, since the user clicking on the page-level Component 2 invoking button represents a light dismiss signal for Component 1, so it closes either way. But this CL simplifies the implementation considerably, removing the need to track all invokers on the page, and also removing the need to continuously check whether invoker relationships have changed. Spec PR: whatwg/html#9171 [1] whatwg/html#9160 Bug: 1307772 Change-Id: I60ccb133a79084db8c251218fdbd10684fea947b Cq-Do-Not-Cancel-Tryjobs: true Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4429412 Commit-Queue: Mason Freed <masonf@chromium.org> Code-Coverage: Findit <findit-for-me@appspot.gserviceaccount.com> Reviewed-by: Joey Arhar <jarhar@chromium.org> Cr-Commit-Position: refs/heads/main@{#1131606} -- wpt-commits: 5acfa513ebd07b44adc8be2fc2c491e1b90236da wpt-pr: 39560
I haven't looked into this part too deeply regarding user implications, but yeah, calling this before the hierarchy is used seems reasonable. |
Please update the commit message to indicate this will close #9168 as well. |
done |
</ol> | ||
</li> | ||
<li><p>Run <var>checkAncestor</var> given <var>newPopover</var>'s <span>popover | ||
invoker</span>.</p></li> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we add an assert here that newPopover is showing? As per a3b356e.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tried adding this assert in chromium either at the beginning or end of "find topmost popover ancestor" and it got hit in several tests.
Why should it be showing?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Because only when it's showing do we know that it's set correctly. We don't clear it at a particularly deterministic time at the moment.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So I think the issue is that during showPopover, newPopover won't be showing yet. See showPopover. Step 2 should reset the invoker to null (so we're ok), step 8.2 runs "topmost popover ancestor" (this algo), and step 13 sets it to showing. So a) we're ok, and b) you can't assert that it's showing here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you!
Anne convinced me that #9048 shouldn't be needed anymore. |
Thanks. Even when <div id=p1 popover>
<button id=b popovertarget=b></button>
</div>
<div id=p2 popover>
<div id=p3 popover></div>
</div>
<script>
p1.showPopover();
p2.showPopover(); // Popover stack is now: p1, p2
p2.appendChild(b);
b.popoverTarget = a; // This reverses the ancestor relationships
p3.showPopover(); // P1 closes here
</script> At the end, p1 closes because the ancestor relationship is p2->p1 and p2->p3, so opening p3 closes p1. Perhaps that's fine. This isn't a great example, since it seems "fine". I'm just wondering if there are worse examples where bad things happen. Maybe not? |
@annevk Can you elaborate your reasoning here? |
Hmm, I was thinking about risky times to use a popover's popover invoker and it not being risky when we check that the popover is showing before using the popover invoker, based on what you wrote in #9171 (comment) (hence the assert suggestion). But I don't think I have a good enough mental model of the popover stack to rule out all issues there. |
Ok. Perhaps the best way forward, for now, is to not do any "checking and closing the popover stack" for now, and revisit this later if problematic use cases arise? I feel like they might not materialize and the current behavior might turn out to be ok. In other words, let's just abandon #9048 for now. |
I think that's okay, I do think we should add the assert I suggested after approving this PR. |
I think you mean this conversation - see my latest comment. I don't think we can add that assert. |
</ol> | ||
</li> | ||
<li><p>Run <var>checkAncestor</var> given <var>newPopover</var>'s <span>popover | ||
invoker</span>.</p></li> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you!
…emilio The invoker type is currently implemented as boolean as suggested at whatwg/html#9168. This issue is now closed and has been fixed at whatwg/html#9171. This patch is to be follow above discussions and implement popover invoker type as element. Differential Revision: https://phabricator.services.mozilla.com/D178287
…emilio The invoker type is currently implemented as boolean as suggested at whatwg/html#9168. This issue is now closed and has been fixed at whatwg/html#9171. This patch is to be follow above discussions and implement popover invoker type as element. Differential Revision: https://phabricator.services.mozilla.com/D178287
…emilio The invoker type is currently implemented as boolean as suggested at whatwg/html#9168. This issue is now closed and has been fixed at whatwg/html#9171. This patch is to be follow above discussions and implement popover invoker type as element. Differential Revision: https://phabricator.services.mozilla.com/D178287
…emilio The invoker type is currently implemented as boolean as suggested at whatwg/html#9168. This issue is now closed and has been fixed at whatwg/html#9171. This patch is to be follow above discussions and implement popover invoker type as element. Differential Revision: https://phabricator.services.mozilla.com/D178287
…emilio The invoker type is currently implemented as boolean as suggested at whatwg/html#9168. This issue is now closed and has been fixed at whatwg/html#9171. This patch is to be follow above discussions and implement popover invoker type as element. Differential Revision: https://phabricator.services.mozilla.com/D178287 UltraBlame original commit: 31915ad324761c4fe80dac65ca36f070ab2102a2
…emilio The invoker type is currently implemented as boolean as suggested at whatwg/html#9168. This issue is now closed and has been fixed at whatwg/html#9171. This patch is to be follow above discussions and implement popover invoker type as element. Differential Revision: https://phabricator.services.mozilla.com/D178287 UltraBlame original commit: 934b572f87f75a1aa549ef81f2a8068b67d9db9a
…emilio The invoker type is currently implemented as boolean as suggested at whatwg/html#9168. This issue is now closed and has been fixed at whatwg/html#9171. This patch is to be follow above discussions and implement popover invoker type as element. Differential Revision: https://phabricator.services.mozilla.com/D178287 UltraBlame original commit: 31915ad324761c4fe80dac65ca36f070ab2102a2
…emilio The invoker type is currently implemented as boolean as suggested at whatwg/html#9168. This issue is now closed and has been fixed at whatwg/html#9171. This patch is to be follow above discussions and implement popover invoker type as element. Differential Revision: https://phabricator.services.mozilla.com/D178287 UltraBlame original commit: 934b572f87f75a1aa549ef81f2a8068b67d9db9a
…emilio The invoker type is currently implemented as boolean as suggested at whatwg/html#9168. This issue is now closed and has been fixed at whatwg/html#9171. This patch is to be follow above discussions and implement popover invoker type as element. Differential Revision: https://phabricator.services.mozilla.com/D178287 UltraBlame original commit: 31915ad324761c4fe80dac65ca36f070ab2102a2
…emilio The invoker type is currently implemented as boolean as suggested at whatwg/html#9168. This issue is now closed and has been fixed at whatwg/html#9171. This patch is to be follow above discussions and implement popover invoker type as element. Differential Revision: https://phabricator.services.mozilla.com/D178287 UltraBlame original commit: 934b572f87f75a1aa549ef81f2a8068b67d9db9a
…emilio The invoker type is currently implemented as boolean as suggested at whatwg/html#9168. This issue is now closed and has been fixed at whatwg/html#9171. This patch is to be follow above discussions and implement popover invoker type as element. Differential Revision: https://phabricator.services.mozilla.com/D178287
…emilio The invoker type is currently implemented as boolean as suggested at whatwg/html#9168. This issue is now closed and has been fixed at whatwg/html#9171. This patch is to be follow above discussions and implement popover invoker type as element. Differential Revision: https://phabricator.services.mozilla.com/D178287 UltraBlame original commit: 1e825b150a60ac26b0f652679eca1b223354fb64
…emilio The invoker type is currently implemented as boolean as suggested at whatwg/html#9168. This issue is now closed and has been fixed at whatwg/html#9171. This patch is to be follow above discussions and implement popover invoker type as element. Differential Revision: https://phabricator.services.mozilla.com/D178287 UltraBlame original commit: 1e825b150a60ac26b0f652679eca1b223354fb64
…emilio The invoker type is currently implemented as boolean as suggested at whatwg/html#9168. This issue is now closed and has been fixed at whatwg/html#9171. This patch is to be follow above discussions and implement popover invoker type as element. Differential Revision: https://phabricator.services.mozilla.com/D178287 UltraBlame original commit: 1e825b150a60ac26b0f652679eca1b223354fb64
…emilio The invoker type is currently implemented as boolean as suggested at whatwg/html#9168. This issue is now closed and has been fixed at whatwg/html#9171. This patch is to be follow above discussions and implement popover invoker type as element. Differential Revision: https://phabricator.services.mozilla.com/D178287
Fixes #9160
Fixes #9168
If this patch is merged, then #9048 is obsolete and can be closed without merging.
Rationale (copied from masons patch):
Instead of using just
the DOM structure to establish the popover hierarchy, the user's behavior should matter. For example, if one popover contains a popover invoker pointing to another popover, it should matter whether that invoker is actually used to open the second popover.
An example:
In this example, the page should be able to still independently use these components. So a user clicking the page's button for Component 2 is expected to close Component 1 if it's open, because that's a direct invocation of Component 2. However, if the user clicks the button within Component 1 to get Component 2, it is natural to leave Component 1 open because this is a nested call.
Important note: this often happens to be the behavior even before this change, since the user clicking on the page-level Component 2 invoking button represents a light dismiss signal for Component 1, so it closes either way. But this patch simplifies the implementation, removing the need to track all invokers on the page, and also removing the need to continuously check whether invoker relationships have changed.
(See WHATWG Working Mode: Changes for more details.)
/popover.html ( diff )