Skip to content

Implement new/revised popover=hint behavior#59237

Merged
chromium-wpt-export-bot merged 5 commits into
masterfrom
chromium-export-cl-7727959
May 14, 2026
Merged

Implement new/revised popover=hint behavior#59237
chromium-wpt-export-bot merged 5 commits into
masterfrom
chromium-export-cl-7727959

Conversation

@chromium-wpt-export-bot

@chromium-wpt-export-bot chromium-wpt-export-bot commented Apr 15, 2026

Copy link
Copy Markdown
Collaborator

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 <masonf@chromium.org>
Reviewed-by: David Baron <dbaron@chromium.org>
Commit-Queue: David Baron <dbaron@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1615186}

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 1 pipeline(s).

@chromium-wpt-export-bot chromium-wpt-export-bot marked this pull request as ready for review April 15, 2026 15:53
@chromium-wpt-export-bot chromium-wpt-export-bot requested a review from a team as a code owner April 15, 2026 15:53
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 <masonf@chromium.org>
Reviewed-by: David Baron <dbaron@chromium.org>
Commit-Queue: David Baron <dbaron@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1615186}

@wpt-pr-bot wpt-pr-bot left a comment

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.

The review process for this patch is being conducted in the Chromium project.

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 1 pipeline(s).

1 similar comment
@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 1 pipeline(s).

@jgraham

jgraham commented Apr 20, 2026

Copy link
Copy Markdown
Contributor

@jakearchibald are you able to review this change?

@jakearchibald

Copy link
Copy Markdown
Contributor

Yeah, I'm planning to go through it today

@jakearchibald jakearchibald left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Looks good so far! Just needs to cater for the newer stuff:

  • Auto can be within hint (but it downgrades).
  • showPopover within the hide/show of a popover should throw/no-op.

I think you mentioned there was a test here somewhere that tested incorrect behaviour… well… I failed to find it. Hah!

Comment thread html/semantics/popovers/popover-hint-hierarchy.html
Comment on lines +106 to +126
// this is "weirdness 5" from https://github.com/whatwg/html/issues/12304
promise_test(async (t) => {
t.add_cleanup(hideAll);

hint1.showPopover();
assertOpen('initial',hint1);

// Imperative
assert_throws_dom('InvalidStateError', () => {
auto1.showPopover({source: hint1});
}, 'Opening auto popover inside hint popover is not allowed');
assertOpen('after show',hint1);

// Declarative
const invoker = document.createElement('button');
invoker.popoverTargetElement = auto1;
t.add_cleanup(() => invoker.remove());
hint1.appendChild(invoker);
await clickOn(invoker);
assertOpen('after click',hint1);
}, 'Opening an auto popover inside a hint popover is disallowed and will fail.');

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

You may have already done this, but in case it helps…

Suggested change
// this is "weirdness 5" from https://github.com/whatwg/html/issues/12304
promise_test(async (t) => {
t.add_cleanup(hideAll);
hint1.showPopover();
assertOpen('initial',hint1);
// Imperative
assert_throws_dom('InvalidStateError', () => {
auto1.showPopover({source: hint1});
}, 'Opening auto popover inside hint popover is not allowed');
assertOpen('after show',hint1);
// Declarative
const invoker = document.createElement('button');
invoker.popoverTargetElement = auto1;
t.add_cleanup(() => invoker.remove());
hint1.appendChild(invoker);
await clickOn(invoker);
assertOpen('after click',hint1);
}, 'Opening an auto popover inside a hint popover is disallowed and will fail.');
// this is "weirdness 5" from https://github.com/whatwg/html/issues/12304
promise_test(async (t) => {
t.add_cleanup(hideAll);
auto1.showPopover();
hint1.showPopover({source: auto1});
assertOpen('initial', auto1, hint1);
auto2.showPopover({source: hint1});
assertOpen('auto opened inside hint', auto1, hint1, auto2);
hint2.showPopover({source: hint1});
assertOpen('auto exhibits hint-like behavior', auto1, hint1, hint2);
}, 'Auto popovers opened inside hint popovers are downgraded to hint behaviors');

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Yeah, this is done in this change.

Comment on lines 97 to 115
<div>
<div popover="hint">Hint
<div popover>Nested auto (note - never visible, since inside display:none subtree)</div>
</div>
<script>
test(() => {
const hint = getPopovers()[0];
const auto = getPopovers()[1];
hint.showPopover();
assertState([true,false]);
auto.showPopover();
assertState([false,true]);
auto.hidePopover();
assert_throws_dom('InvalidStateError', () => {
auto.showPopover();
});
assertState([true,false]);
hint.hidePopover();
assertState([false,false]);
},'If a popover=auto is shown, it should hide any open popover=hint, including if the popover=hint is an ancestral popover of the popover=auto. (You can\'t nest a popover=auto inside a popover=hint)');
</script>
</div>

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggested change
<div>
<div popover="hint">Hint
<div popover>Nested auto</div>
</div>
<script>
test(() => {
const hint = getPopovers()[0];
const auto = getPopovers()[1];
hint.showPopover();
assertState([true,false]);
auto.showPopover();
assertState([true,true]);
hint.hidePopover();
assertState([false,false]);
},'If a popover=auto is shown within a popover=hint, it should be shown');
</script>
</div>

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Comment thread html/semantics/popovers/popover-types-with-hints.html Outdated

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Need to cater for 'auto' being allowed inside 'hint'. Watch out for stuff outside tests too, like "Improperly nested".

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This is handled in #3 of the followup CLs:

whatwg/html#12345 (comment)

Comment thread html/semantics/popovers/resources/popover-top-layer-nesting.js
@jonathan-j-lee

Copy link
Copy Markdown
Contributor

@mfreed7 To address the review, you can push some extra commits on this branch. The changes will propagate back to chromium/src on the next import.

mfreed7 and others added 4 commits April 23, 2026 13:53
Co-authored-by: Jake Archibald <jaffathecake@gmail.com>
Co-authored-by: Jake Archibald <jaffathecake@gmail.com>
@mfreed7

mfreed7 commented Apr 23, 2026

Copy link
Copy Markdown
Contributor

@mfreed7 To address the review, you can push some extra commits on this branch. The changes will propagate back to chromium/src on the next import.

I'm guessing they will then create additional havoc with the dependent patches that change the same tests, but I guess we'll see!

@mfreed7

mfreed7 commented May 5, 2026

Copy link
Copy Markdown
Contributor

Can we land this?

@jonathan-j-lee

Copy link
Copy Markdown
Contributor

@jakearchibald @jgraham ^

annevk pushed a commit to whatwg/html that referenced this pull request May 14, 2026
- Showing a hint popover doesn't hide auto popovers.
- Showing a hint popover hides non-parent hint popovers.
- Clicking outside popovers consistently hides them.
- Hiding an auto popover does not hide unrelated hint popovers.
- Showing an auto popover as a child of a hint popover downgrades the auto popover to a hint.
- Showing a popover during the show or hide of another popover is no longer allowed.

Tests: web-platform-tests/wpt#59237.

Fixes #12304, fixes #12346 fixes #12355, and fixes #12356.

@jgraham jgraham left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

From an Interop point of view, this is approved by the vendors who are affected by the change, so it's fine to land.

@chromium-wpt-export-bot chromium-wpt-export-bot merged commit 7c5c871 into master May 14, 2026
25 checks passed
@chromium-wpt-export-bot chromium-wpt-export-bot deleted the chromium-export-cl-7727959 branch May 14, 2026 10:12
@mfreed7

mfreed7 commented May 14, 2026

Copy link
Copy Markdown
Contributor

From an Interop point of view, this is approved by the vendors who are affected by the change, so it's fine to land.

Thanks!

@jonathan-j-lee, do you happen to know how long it takes Chromium's infra to upload the next in the series? I'd love to get all of those landed, so that we can make sure the final collection looks good to everyone. It's pretty difficult to do that as-is.

@jonathan-j-lee

Copy link
Copy Markdown
Contributor

I've paused @chromium-wpt-export-bot because of crashes related to jj using Link instead of Change-Id footers (https://crbug.com/513548026#comment2). @patrykchodur
has contributed a fix here: https://crrev.com/c/7852456

@mfreed7

mfreed7 commented May 18, 2026

Copy link
Copy Markdown
Contributor

I've paused @chromium-wpt-export-bot because of crashes related to jj using Link instead of Change-Id footers (https://crbug.com/513548026#comment2). @patrykchodur has contributed a fix here: https://crrev.com/c/7852456

Thanks @jonathan-j-lee. It also seems like the importer is borked because of the changes made during the review of this PR: https://crbug.com/513412137.

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants