From cb6cce3c51bb09af7c39e82cce2d6a6383e52c09 Mon Sep 17 00:00:00 2001 From: Totati Date: Fri, 19 Jul 2024 08:46:30 +0200 Subject: [PATCH] Add support for slotting elements into popovers --- index.html | 44 ++++++++++++++++++++++++++++++++++++++++++ src/popover-helpers.ts | 5 ++++- tests/dismiss.spec.ts | 14 ++++++++++++++ 3 files changed, 62 insertions(+), 1 deletion(-) diff --git a/index.html b/index.html index 27c2c34..6625729 100644 --- a/index.html +++ b/index.html @@ -676,6 +676,50 @@

<div id="shadowedPopover" popover>Shadowed Popover</div> <div> <div id="shadowedNestedPopover" popover>Shadowed Nested Popover</div> +</div> + + +
+

+ + Element slotted in an Shadow Root Popover +

+

+ Here, both the popover control button and the popover are created in + the Shadow DOM, but an element is slotted in the popover +

+
+
I'm a slotted element
+
+ +
<!-- Shadow DOM -->
+<button popovertarget="shadowedPopoverWithSlot">
+  Toggle Shadowed Popover
+</button>
+
+<div id="shadowedPopoverWithSlot" popover>
+  </slot></slot>
 </div>
diff --git a/src/popover-helpers.ts b/src/popover-helpers.ts index 46e65bd..17db3b5 100644 --- a/src/popover-helpers.ts +++ b/src/popover-helpers.ts @@ -113,7 +113,10 @@ function nearestInclusiveOpenPopover( ) { return node; } - node = node.parentElement || getRootNode(node); + node = + (node instanceof Element && node.assignedSlot) || + node.parentElement || + getRootNode(node); if (node instanceof ShadowRoot) node = node.host; if (node instanceof Document) return; } diff --git a/tests/dismiss.spec.ts b/tests/dismiss.spec.ts index d4f0477..4f7b740 100644 --- a/tests/dismiss.spec.ts +++ b/tests/dismiss.spec.ts @@ -114,3 +114,17 @@ test('pressing Escape focused in popover dismisses auto popovers', async ({ await expect(singleActionShowPopover).toBeHidden(); }); + +test('click inside auto popover with a slotted element does not dismiss itself', async ({ + page, +}) => { + const testPopover = (await page.locator('#shadowedPopoverWithSlot')).nth(0); + await expect( + await testPopover.evaluate((node) => node.showPopover()), + ).toBeUndefined(); + await expect(testPopover).toBeVisible(); + + const slottedText = (await page.locator('#shadowHostWithSlot span')).nth(0); + await slottedText.evaluate((node) => node.click()); + await expect(testPopover).toBeVisible(); +});