Skip to content

Commit 44ae1c4

Browse files
mfreed7chromium-wpt-export-bot
authored andcommitted
Add :closed pseudo class, for the pop-up API only
Per the [1] resolution, the CSSWG will be adding both :open (which is already implemented for pop-up) and :closed (which this CL adds). At this point, both `:open` and `:closed` are only supported for the pop-up API, and only with the HTMLPopupAttribute feature enabled. More general support for other elements will be added later. [1] w3c/csswg-drafts#7319 (comment) Bug: 1307772 Change-Id: If0c27f1f8c7a30fc00656d5eeafe4b6c21bba890 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3961537 Reviewed-by: Joey Arhar Commit-Queue: Mason Freed Auto-Submit: Mason Freed Cr-Commit-Position: refs/heads/main@{#1063120}
1 parent ad8a1a6 commit 44ae1c4

File tree

2 files changed

+40
-2
lines changed

2 files changed

+40
-2
lines changed

html/semantics/popups/popup-animation-corner-cases.tentative.html

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,14 +45,18 @@
4545
const {popUp, descendent} = createPopUp(t,'animation');
4646
assert_false(isElementVisible(popUp));
4747
assert_equals(descendent.parentElement.parentElement,popUp);
48+
assert_true(popUp.matches(':closed'));
49+
assert_false(popUp.matches(':open'));
4850
popUp.showPopUp();
51+
assert_false(popUp.matches(':closed'));
4952
assert_true(popUp.matches(':open'));
5053
assert_true(isElementVisible(popUp));
5154
assert_equals(popUp.getAnimations({subtree: true}).length,0);
5255
popUp.hidePopUp();
5356
const animations = popUp.getAnimations({subtree: true});
5457
assert_equals(animations.length,2,'There should be two animations running');
5558
assert_false(popUp.matches(':open'),'popUp should not match :open as soon as hidden');
59+
assert_false(popUp.matches(':closed'),'popUp should not match :closed until animations complete');
5660
assert_true(isElementVisible(popUp),'but animations should keep the popUp visible');
5761
assert_true(isElementVisible(descendent),'The descendent should also be visible');
5862
await waitForRender();
@@ -61,6 +65,7 @@
6165
assert_true(isElementVisible(popUp),'PopUp should still be visible due to animation');
6266
animations.forEach(animation => animation.finish()); // Force the animations to finish
6367
await waitForRender(); // Wait one frame
68+
assert_true(popUp.matches(':closed'),'The pop up should now match :closed');
6469
assert_false(popUp.matches(':open'),'The pop up still shouldn\'t match :open');
6570
assert_false(isElementVisible(popUp),'The pop up should now be invisible');
6671
assert_false(isElementVisible(descendent),'The descendent should also be invisible');
@@ -82,6 +87,7 @@
8287
// Then hide the popUp.
8388
popUp.hidePopUp();
8489
assert_false(popUp.matches(':open'),'pop up should not match :open as soon as hidden');
90+
assert_true(popUp.matches(':closed'),'pop up should match :closed immediately');
8591
assert_equals(popUp.getAnimations({subtree: true}).length,2,'animations should still be running');
8692
await waitForRender();
8793
assert_equals(popUp.getAnimations({subtree: true}).length,2,'animations should still be running');
@@ -137,6 +143,27 @@
137143
assert_false(isElementVisible(popUp),'Even if hide event is cancelled, the popup still closes');
138144
},'hide event cannot be cancelled');
139145

146+
promise_test(async (t) => {
147+
const {popUp, descendent} = createPopUp(t,'animation');
148+
assert_false(isElementVisible(popUp));
149+
popUp.showPopUp();
150+
assert_false(popUp.matches(':closed'));
151+
assert_true(popUp.matches(':open'));
152+
assert_true(isElementVisible(popUp));
153+
assert_equals(popUp.getAnimations({subtree: true}).length,0);
154+
popUp.popUp = 'manual';
155+
const animations = popUp.getAnimations({subtree: true});
156+
assert_equals(animations.length,2,'There should be two animations running');
157+
assert_false(popUp.matches(':open'),'popUp should not match :open as soon as hidden');
158+
assert_false(popUp.matches(':closed'),'popUp should not match :closed until animations complete');
159+
assert_true(isElementVisible(popUp),'but animations should keep the popUp visible');
160+
animations.forEach(animation => animation.finish()); // Force the animations to finish
161+
await waitForRender(); // Wait one frame
162+
assert_true(popUp.matches(':closed'),'The pop up should now match :closed');
163+
assert_false(popUp.matches(':open'),'The pop up still shouldn\'t match :open');
164+
assert_false(isElementVisible(popUp),'The pop up should now be invisible');
165+
},'Closing animations are triggered by changing the pop-up type');
166+
140167
promise_test(async (t) => {
141168
const {popUp, descendent} = createPopUp(t,'');
142169
popUp.showPopUp();

html/semantics/popups/popup-attribute-basic.tentative.html

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,9 +47,11 @@
4747
if (isVisible) {
4848
assert_not_equals(window.getComputedStyle(popUp).display,'none');
4949
assert_equals(popUp.matches(':open'),isPopUp,`${message}: Visible pop-ups should match :open`);
50+
assert_false(popUp.matches(':closed'),`${message}: Visible pop-ups and *all* non-pop-ups should *not* match :closed`);
5051
} else {
5152
assert_equals(window.getComputedStyle(popUp).display,'none',`${message}: Non-showing pop-ups should have display:none`);
5253
assert_false(popUp.matches(':open'),`${message}: Non-showing pop-ups should *not* match :open`);
54+
assert_true(popUp.matches(':closed'),`${message}: Non-showing pop-ups should match :closed`);
5355
}
5456
}
5557
function assertIsFunctionalPopUp(popUp) {
@@ -89,7 +91,7 @@
8991
});
9092

9193
// Then loop through all HTML5 elements that render a box by default:
92-
let elementsThatDontRender = ['audio','base','br','datalist','dialog','embed','head','link','meta','noscript','param','rp','script','style','template','title','wbr'];
94+
let elementsThatDontRender = ['audio','base','br','datalist','dialog','embed','head','link','meta','noscript','param','rp','script','slot','style','template','title','wbr'];
9395
const elements = HTML5_ELEMENTS.filter(el => !elementsThatDontRender.includes(el));
9496
elements.forEach(tag => {
9597
test((t) => {
@@ -98,7 +100,13 @@
98100
document.body.appendChild(element);
99101
t.add_cleanup(() => element.remove());
100102
assertIsFunctionalPopUp(element);
101-
}, `A <${tag}> element should behave as a pop-up.`);
103+
}, `A <${tag} popup> element should behave as a pop-up.`);
104+
test((t) => {
105+
const element = document.createElement(tag);
106+
document.body.appendChild(element);
107+
t.add_cleanup(() => element.remove());
108+
assertNotAPopUp(element);
109+
}, `A <${tag}> element should *not* behave as a pop-up.`);
102110
});
103111

104112
function createPopUp(t) {
@@ -318,17 +326,20 @@
318326
assert_false(isElementVisible(popUp));
319327
popUp.showPopUp();
320328
assert_true(popUp.matches(':open'));
329+
assert_false(popUp.matches(':closed'));
321330
assert_true(getComputedStyle(popUp).opacity < 0.1,'Animations should start on show');
322331
assert_throws_dom("InvalidStateError",() => popUp.showPopUp(),'Calling showPopUp on a popup that is in the process of animating show should throw InvalidStateError');
323332
await finishAnimations(popUp);
324333
assert_true(getComputedStyle(popUp).opacity > 0.9);
325334
assert_true(isElementVisible(popUp));
326335
popUp.hidePopUp();
327336
assert_false(popUp.matches(':open'));
337+
assert_false(popUp.matches(':closed'),'Not :closed until animations finish');
328338
assert_true(getComputedStyle(popUp).opacity > 0.9,'Animations should start on hide');
329339
assert_throws_dom("InvalidStateError",() => popUp.hidePopUp(),'Calling hidePopUp on a popup that is in the process of animating hide should throw InvalidStateError');
330340
popUp.showPopUp(); // But showPopUp should still be ok.
331341
popUp.hidePopUp(); // Clean up
332342
await finishAnimations(popUp);
343+
assert_true(popUp.matches(':closed'),':closed should match once animations finish');
333344
},'Exceptions are thrown even when show/hide are animated')
334345
script>

0 commit comments

Comments
 (0)