Skip to content

Simplify popover=hint behaviours & related spec fixes#12345

Open
jakearchibald wants to merge 22 commits intomainfrom
jakearchibald/popover-hint-simpler-behaviours
Open

Simplify popover=hint behaviours & related spec fixes#12345
jakearchibald wants to merge 22 commits intomainfrom
jakearchibald/popover-hint-simpler-behaviours

Conversation

@jakearchibald
Copy link
Copy Markdown
Collaborator

@jakearchibald jakearchibald commented Apr 8, 2026

(See WHATWG Working Mode: Changes for more details.)

Fixes #12304.

Fixes #12346.

Fixes #12355.

Fixes #12356.


/infrastructure.html ( diff )
/interactive-elements.html ( diff )
/popover.html ( diff )

Comment thread source Outdated
@jakearchibald
Copy link
Copy Markdown
Collaborator Author

jakearchibald commented Apr 8, 2026

I'll sort out the wrapping after reviews & changes.

@jakearchibald jakearchibald marked this pull request as ready for review April 8, 2026 14:01
@lukewarlow
Copy link
Copy Markdown
Member

Btw https://github.com/domfarolino/specfmt is quite useful for the wrapping.

@jakearchibald
Copy link
Copy Markdown
Collaborator Author

@lukewarlow haha your deleted comment did reveal a bug! It wasn't the return false that was wrong, but I was missing a return true.

@jakearchibald
Copy link
Copy Markdown
Collaborator Author

jakearchibald commented Apr 8, 2026

Edit: I've broken this out into #12355

av1.mp4

@mfreed7 sorry for another video, but I don't think I'd be able to describe it well. What do you see as the intended behaviour here?

https://random-stuff.jakearchibald.com/bug-repros/popover-show-on-hide-warning/ - here's the demo page.

Edit: I'm not convinced my spec totally solves this either, as hiding a popover hides child popovers, which would include the new ones added, and they'd be hidden with events. Maybe.

Comment thread source Outdated
Comment thread source Outdated
Comment thread source Outdated
Comment thread source Outdated
Comment thread source Outdated
Comment thread source Outdated
Comment thread source Outdated
Comment thread source Outdated
Comment thread source Outdated
Comment thread source Outdated
Comment thread source Outdated
@jakearchibald
Copy link
Copy Markdown
Collaborator Author

@mfreed7 can you create a PR for your tests so far?

Comment thread source Outdated
<span>"<code>InvalidStateError</code>"</span> <code>DOMException</code>.</p></li>

<li><p>Return false.</p></li>
</ol>
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment thread source Outdated
Comment thread source Outdated
Comment thread source Outdated
@mfreed7
Copy link
Copy Markdown
Collaborator

mfreed7 commented Apr 14, 2026

@mfreed7 can you create a PR for your tests so far?

Yes. Our infra used to file a PR as soon as a Chromium CL went to the review-requested state, but it apparently no longer does that. Since I'm still waiting on the review, the new tests are located here for now:

https://chromium-review.git.corp.google.com/c/chromium/src/+/7727959

@jakearchibald
Copy link
Copy Markdown
Collaborator Author

@mfreed7 cool I'll give them a full review when there's a wpt PR. Could you review this PR?

chromium-wpt-export-bot pushed a commit to web-platform-tests/wpt that referenced this pull request Apr 15, 2026
See this discussion for more context:

whatwg/html#12304
whatwg/html#12345

This CL implements a simplified behavioral model for popover=hint and
popover=auto, cleanly separating the autoRootedPopoverStack from the
hintRootedPopoverStack and introducing a `hintStackParent` to track
where the hint stack branches off the auto stack.

The new behavior resolves the following inconsistencies (gated behind
the `PopoverHintNewBehavior` experimental runtime flag):

1. Opening a hint popover will not hide unrelated auto popovers.
2. Opening a hint popover closes only other non-ancestor hint
   popovers.
3. Clicking outside consistently closes both auto and hint popovers.
4. Hiding an auto popover closes only its child popovers.
5. Opening an auto popover inside a hint popover is disallowed and
   will fail.

A new WPT test (`popover-hint-hierarchy.html`) is added to explicitly
assert these 5 rules, and existing popover WPTs are updated to reflect
the new behavior. A virtual test suite (`popover-hint-old-behavior`)
is also added to continue testing the legacy behavior. I'm not sure
how to best handle the changed tests (and I guess the new test too)
in the context of a spec PR that is forthcoming. I'd like to be able
to publish (as a WPT PR at least) the changes, to help with the PR
effort. Suggestions appreciated.

A note about the diff: I made all of the feature flag checks look like
`if (!feature enabled) {` in the hopes that the old code would show
as unchanged in the diff, but gerrit's diff algorithm isn't great.
It's at least a little better like this than if I put the new code
first, so I left it.

Bug: 4990199
Change-Id: I41d8d96be71ba60ec5e7aa640c935258d1e33431
@mfreed7
Copy link
Copy Markdown
Collaborator

mfreed7 commented Apr 15, 2026

@mfreed7 cool I'll give them a full review when there's a wpt PR. Could you review this PR?

web-platform-tests/wpt#59237

And yes! I've been swamped but I'll give the PR a look right now.

beckysiegel pushed a commit to chromium/chromium that referenced this pull request Apr 15, 2026
See this discussion for more context:

whatwg/html#12304
whatwg/html#12345

This CL implements a simplified behavioral model for popover=hint and
popover=auto, cleanly separating the autoRootedPopoverStack from the
hintRootedPopoverStack and introducing a `hintStackParent` to track
where the hint stack branches off the auto stack.

The new behavior resolves the following inconsistencies (gated behind
the `PopoverHintNewBehavior` experimental runtime flag):

1. Opening a hint popover will not hide unrelated auto popovers.
2. Opening a hint popover closes only other non-ancestor hint
   popovers.
3. Clicking outside consistently closes both auto and hint popovers.
4. Hiding an auto popover closes only its child popovers.
5. Opening an auto popover inside a hint popover is disallowed and
   will fail.

A new WPT test (`popover-hint-hierarchy.html`) is added to explicitly
assert these 5 rules, and existing popover WPTs are updated to reflect
the new behavior. A virtual test suite (`popover-hint-old-behavior`)
is also added to continue testing the legacy behavior. I'm not sure
how to best handle the changed tests (and I guess the new test too)
in the context of a spec PR that is forthcoming. I'd like to be able
to publish (as a WPT PR at least) the changes, to help with the PR
effort. Suggestions appreciated.

A note about the diff: I made all of the feature flag checks look like
`if (!feature enabled) {` in the hopes that the old code would show
as unchanged in the diff, but gerrit's diff algorithm isn't great.
It's at least a little better like this than if I put the new code
first, so I left it.

Bug: 499019927
Change-Id: I41d8d96be71ba60ec5e7aa640c935258d1e33431
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7727959
Auto-Submit: Mason Freed <[email protected]>
Reviewed-by: David Baron <[email protected]>
Commit-Queue: David Baron <[email protected]>
Cr-Commit-Position: refs/heads/main@{#1615186}
Copy link
Copy Markdown
Member

@annevk annevk left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Editorially this looks fine now, thanks for the Infra updates! Please let me know when OP is complete, tests have been reviewed, and at least one person involved did a comprehensive technical review.

Comment thread source Outdated
chromium-wpt-export-bot pushed a commit to web-platform-tests/wpt that referenced this pull request Apr 15, 2026
See this discussion for more context:

whatwg/html#12304
whatwg/html#12345

This CL implements a simplified behavioral model for popover=hint and
popover=auto, cleanly separating the autoRootedPopoverStack from the
hintRootedPopoverStack and introducing a `hintStackParent` to track
where the hint stack branches off the auto stack.

The new behavior resolves the following inconsistencies (gated behind
the `PopoverHintNewBehavior` experimental runtime flag):

1. Opening a hint popover will not hide unrelated auto popovers.
2. Opening a hint popover closes only other non-ancestor hint
   popovers.
3. Clicking outside consistently closes both auto and hint popovers.
4. Hiding an auto popover closes only its child popovers.
5. Opening an auto popover inside a hint popover is disallowed and
   will fail.

A new WPT test (`popover-hint-hierarchy.html`) is added to explicitly
assert these 5 rules, and existing popover WPTs are updated to reflect
the new behavior. A virtual test suite (`popover-hint-old-behavior`)
is also added to continue testing the legacy behavior. I'm not sure
how to best handle the changed tests (and I guess the new test too)
in the context of a spec PR that is forthcoming. I'd like to be able
to publish (as a WPT PR at least) the changes, to help with the PR
effort. Suggestions appreciated.

A note about the diff: I made all of the feature flag checks look like
`if (!feature enabled) {` in the hopes that the old code would show
as unchanged in the diff, but gerrit's diff algorithm isn't great.
It's at least a little better like this than if I put the new code
first, so I left it.

Bug: 4990199
Change-Id: I41d8d96be71ba60ec5e7aa640c935258d1e33431
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7727959
Auto-Submit: Mason Freed <[email protected]>
Reviewed-by: David Baron <[email protected]>
Commit-Queue: David Baron <[email protected]>
Cr-Commit-Position: refs/heads/main@{#1615186}
Copy link
Copy Markdown
Collaborator

@mfreed7 mfreed7 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks pretty good to me. Thanks again for putting it together.

Comment thread source Outdated
Comment thread source
Comment thread source
<ol>
<li><p>Run <span>close entire popover list</span> given <var>document</var>'s <span>showing
hint popover list</span>, <var>focusPreviousElement</var>, and <var>fireEvents</var>.</p></li>
<li><p>If <var>endpointIsHint</var>, then return.</p></li>
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So with this behavior, if you have an Auto popover (A1), which opens a Hint popover (H1). You also have another Auto popover (A2) opened higher/later in the auto stack. The user clicks inside H1. I thought (and implemented) that in this case, A2 should be closed, because A1 is H1's hint stack parent. But this algorithm won't do that. Is that intentional? Your proposal says "Proposed: All auto/hint popovers are closed except any clicked popover and its parents."

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I'm understanding you correctly, you're talking about a structure like this:

graph TD
    A1 --> A2
    A1 --> H1
Loading

…where H1 is clicked.

Ah, yeah, good catch. It'll stop here and not hide A2.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 3e4a889

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, that's the tree. But I think maybe there's another similar problem still there. With that tree (and A1 being the "hint stack parent"), if you go to open a new A3 (whose invoker is inside A1). During that show (A3.showPopover()), the "topmost popover ancestor" will find A1 to be that ancestor, and we will call "hide popovers until" on A1. But the new "hide popovers until" will first call "hide popover stack until" with A1. Because A1 is in the auto stack, that algorithm will slice the entire hint stack and close it. H1 gets closed, and I think it should stay open.

WDYT? I will add a WPT test case for this, if there isn't one already.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought that opening an auto popover always hides hint popovers? That's what I outlined here anyway #12304 (comment)

Or have I misunderstood?

Comment thread source
Comment thread source Outdated
Comment thread source Outdated
Comment thread source Outdated
@mfreed7
Copy link
Copy Markdown
Collaborator

mfreed7 commented Apr 15, 2026

The new tests I referred to above are here now: https://crrev.com/c/7765209. I'll comment again when those become a WPT PR.

beckysiegel pushed a commit to chromium/chromium that referenced this pull request Apr 16, 2026
This fixes an error in the recently-landed popover=hint behavior at
[1], for this case:

Auto popover (A1) is the anchor for a Hint popover (H1). Another Auto
popover (A2) is opened on top. The Auto stack is [A1, A2] and the
hint_parent is A1.  While hiding all popovers down to A1, the old code
would hide H1, even though it left H1's anchor (A1) open.

It also adds two tests for cases discovered during the review of the
spec PR [2]. Those were correct in Chromium, but incorrect in the
spec.

[1] https://crrev.com/c/7727959
[2] whatwg/html#12345

Bug: 499019927
Change-Id: I917bf939614f9811470444e9f13c942e5c63b1b1
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7765209
Auto-Submit: Mason Freed <[email protected]>
Reviewed-by: David Baron <[email protected]>
Commit-Queue: Mason Freed <[email protected]>
Cr-Commit-Position: refs/heads/main@{#1616163}
@jakearchibald
Copy link
Copy Markdown
Collaborator Author

@keithamus and @mfreed7, hopefully this is it in terms of the behaviour. Aside from editorial stuff, I've changed:

  • Light dismiss (click behaviour) is changed so it correctly closes unrelated auto popovers if a hint is clicked.
  • Topmost popover ancestor algorithm should be doing the correct thing now.
  • Opening a hint popover within an auto popover now downgrades the popover to hint, and allows it to open.
  • Showing a popover during the show/hide of another is no longer allowed.

On that last point, I was pretty heavy-handed, and applied it to all popovers, not just auto/hint. Otherwise, it gets tricky if the popover type changes.

Thank you for all the reviews so far. Up for one more?

I'll take a look at the tests.

@mfreed7
Copy link
Copy Markdown
Collaborator

mfreed7 commented Apr 17, 2026

@keithamus and @mfreed7, hopefully this is it in terms of the behaviour.

Thanks again for taking this on!

  • Opening a hint popover within an auto popover now downgrades the popover to hint, and allows it to open.

This bit is not yet represented in the WPTs, FYI. I don't think I can get to it today, but maybe. Let me know if you edit the WPTs in the meantime. All of the rest should be represented (modulo my note below).

On that last point, I was pretty heavy-handed, and applied it to all popovers, not just auto/hint. Otherwise, it gets tricky if the popover type changes.

I think that's fine. Exceptions are better than confusing situations - they lead to the well lit path.

Thank you for all the reviews so far. Up for one more?

I'll look right now.

I'll take a look at the tests.

Thanks! Note that this set of changes landed in Chromium, but hasn't been put up as a WPT PR yet. I think our infra is having a problem. I've pinged them.

@mfreed7
Copy link
Copy Markdown
Collaborator

mfreed7 commented Apr 17, 2026

Thank you for all the reviews so far. Up for one more?

I'll look right now.

I think the new changes look good, modulo the one I re-opened and commented on. Otherwise, great! I'm getting started on the new/changed WPTs corresponding to the auto-downgrades-to-hint and "loop" prevention stuff.

@mfreed7
Copy link
Copy Markdown
Collaborator

mfreed7 commented Apr 17, 2026

Complete aside: it's cool and it's also a problem that you've grabbed PR #12345. My LLM wrote that into a comment, and I just naturally assumed it hallucinated the number.

Comment thread source

<p>Every <span data-x="HTML elements">HTML element</span> has a <dfn>popover showing or
hiding</dfn>, which is a boolean, initially set to false.</p>
<p>Every <span data-x="HTML elements">HTML element</span> has a <dfn>popover hiding</dfn>, which is a boolean, initially set to false.</p>
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did you mean to put this bit on Element and not Document? Having it here on Element means you can open a new popover from within the events for another popover, e.g.,

<div id="popoverA" popover="auto">A</div>
<div id="popoverB" popover="auto">B</div>
<script>
popoverA.addEventListener('beforetoggle', (e) => {
  popoverB.showPopover(); // This runs while popover A is half way open
});
popoverA.showPopover();
<script>

Here, popoverB tries to close popoverA before popoverA has finished opening. I think the end state is maybe ok in this case, but it makes me nervous that this is a path to bugs. It seems like maybe this bit should live on Document, next to "hiding popover nesting count"?

Or I'm entirely missing the nuance of the new algorithms.

Copy link
Copy Markdown
Collaborator Author

@jakearchibald jakearchibald Apr 18, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is an existing concept for preventing events on a nested hide of a single popover. I simply renamed it because it previously handled nested showing, but that isn't possible anymore.

There's an additional document-level thing for preventing showing within a show.

Comment thread source

<p>Every <code>Document</code> has a <dfn>hiding popover nesting count</dfn>, which is a number, initially 0.</p>

<p>Every <code>Document</code> has a <dfn>showing popover</dfn>, which is a boolean, initially false.</p>
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mfreed7 this is the concept

Comment thread source
<li><p>Let <var>document</var> be <var>element</var>'s <span>node document</span>.</p></li>

<li>
<p>If <var>document</var>'s <span>showing popover</span> is true, or <var>document</var>'s <span>hiding popover nesting count</span> is not 0, then:</p>
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mfreed7 here's where it's used.

@jakearchibald
Copy link
Copy Markdown
Collaborator Author

@mfreed7

Complete aside: it's cool and it's also a problem that you've grabbed PR #12345. My LLM wrote that into a comment, and I just naturally assumed it hallucinated the number.

Yes! It was really satisfying to grab #12345. Even more-so because, when I noticed the original issue was #12304, I thought "ohhhh, #12345 will be soon! I wonder what that will be".

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

5 participants