From 7c606a2a578383fa63868b1caaf8bd1273db9a11 Mon Sep 17 00:00:00 2001 From: eirikbacker Date: Fri, 24 Apr 2026 14:32:54 +0200 Subject: [PATCH 1/5] fix(Popover): better handle esc when dialog is open --- .../components/dropdown/dropdown.stories.tsx | 48 +++++++++++++++++++ .../react/src/components/popover/popover.tsx | 34 ++++++++----- 2 files changed, 71 insertions(+), 11 deletions(-) diff --git a/packages/react/src/components/dropdown/dropdown.stories.tsx b/packages/react/src/components/dropdown/dropdown.stories.tsx index a27efa4bd3..2b27216db0 100644 --- a/packages/react/src/components/dropdown/dropdown.stories.tsx +++ b/packages/react/src/components/dropdown/dropdown.stories.tsx @@ -221,3 +221,51 @@ WithNestedDialog.play = async (ctx) => { await expect(dialog).toBeInTheDocument(); await waitFor(() => expect(dialog).toBeVisible()); }; + +export const WithAdjacentDialog: StoryFn = (args) => { + return ( + <> + + + Dropdown + + + + + + Dialog + + + + + + Min dialog + + ); +}; + +export const WithNestedDropdown: StoryFn = (args) => { + return ( + + + Dropdown + + + + + + Dropdown + + + + Nested + + + + + + + + + ); +}; diff --git a/packages/react/src/components/popover/popover.tsx b/packages/react/src/components/popover/popover.tsx index 460da63bda..bc6e5ce713 100644 --- a/packages/react/src/components/popover/popover.tsx +++ b/packages/react/src/components/popover/popover.tsx @@ -74,7 +74,6 @@ export type PopoverProps = MergeRight< * Content * */ - export const Popover = forwardRef( function Popover( { @@ -118,16 +117,12 @@ export const Popover = forwardRef( }; const handleKeydown = (event: KeyboardEvent) => { - if (event.key !== 'Escape' || !controlledOpen) return; - const isOpen = - popoverRef.current?.matches(':popover-open') || - popoverRef.current?.classList.contains(':popover-open'); // Polyfill support - - if (!isOpen) return; - event.preventDefault(); // Prevent closing fullscreen in Safari - document.querySelector(trigger)?.focus?.(); // Move focus back to trigger since `popoover="manual"` doesn't do this - setInternalOpen(false); - onClose?.(); + if (event.key === 'Escape' && controlledOpen && isTopLayer(popover)) { + event.preventDefault(); // Prevent closing fullscreen in Safari + document.querySelector(trigger)?.focus?.(); // Move focus back to trigger since `popoover="manual"` doesn't do this + setInternalOpen(false); + onClose?.(); + } }; popover?.togglePopover?.(controlledOpen); @@ -163,3 +158,20 @@ export const Popover = forwardRef( ); }, ); + +// NOTE: This is not able to check if the popover is the most recently added #topLayer, +// so we need another method in time, or remove the controlled popover="manual" in a v2 +const isTopLayer = (checkElement?: Element | null) => { + if (!checkElement) return false; + const { x, y, width, height } = checkElement.getBoundingClientRect(); + const topElement = document.elementFromPoint(x + width / 2, y + height / 2); + + // If the element on top is on browser #top-layer but not same as provided element, then provided element is not on top + for (let el = topElement; el; el = el.parentElement) { + if (checkElement === el) return true; // If the topElement is same as provided element, it's on top + if (el instanceof HTMLDialogElement && el.open) return false; // Check for open dialog + if (el.classList.contains(':popover-open')) return false; // Polyfill support + if (el.matches(':popover-open')) return false; // Native support + } + return false; +}; From dbbc6ea71906468dad851f3876740456a45d6630 Mon Sep 17 00:00:00 2001 From: Eirik Backer Date: Fri, 24 Apr 2026 14:34:45 +0200 Subject: [PATCH 2/5] Create strange-yaks-burn.md --- .changeset/strange-yaks-burn.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/strange-yaks-burn.md diff --git a/.changeset/strange-yaks-burn.md b/.changeset/strange-yaks-burn.md new file mode 100644 index 0000000000..e9631ce33c --- /dev/null +++ b/.changeset/strange-yaks-burn.md @@ -0,0 +1,5 @@ +--- +"@digdir/designsystemet-react": patch +--- + +**Popover):** No longer closes with "Escape" key if a Dialog element is open above the popover From 814a711098d70769262ce1aa07eb192d09cb530b Mon Sep 17 00:00:00 2001 From: Eirik Backer Date: Fri, 24 Apr 2026 14:35:06 +0200 Subject: [PATCH 3/5] Update strange-yaks-burn.md --- .changeset/strange-yaks-burn.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/strange-yaks-burn.md b/.changeset/strange-yaks-burn.md index e9631ce33c..0b13f0066e 100644 --- a/.changeset/strange-yaks-burn.md +++ b/.changeset/strange-yaks-burn.md @@ -2,4 +2,4 @@ "@digdir/designsystemet-react": patch --- -**Popover):** No longer closes with "Escape" key if a Dialog element is open above the popover +**Popover:** No longer closes with "Escape" key if a Dialog element is open above the popover From 18084b74bcc1a9b6daad002c63238f2acd2939e2 Mon Sep 17 00:00:00 2001 From: Eirik Backer Date: Fri, 24 Apr 2026 15:41:33 +0200 Subject: [PATCH 4/5] Update .changeset/strange-yaks-burn.md Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .changeset/strange-yaks-burn.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/strange-yaks-burn.md b/.changeset/strange-yaks-burn.md index 0b13f0066e..704533d5bd 100644 --- a/.changeset/strange-yaks-burn.md +++ b/.changeset/strange-yaks-burn.md @@ -2,4 +2,4 @@ "@digdir/designsystemet-react": patch --- -**Popover:** No longer closes with "Escape" key if a Dialog element is open above the popover +**Popover:** No longer closes with "Escape" key if a Dialog element is open above the popover From c227c27987848c2387d60d144070631ba3a69583 Mon Sep 17 00:00:00 2001 From: Eirik Backer Date: Fri, 24 Apr 2026 15:41:42 +0200 Subject: [PATCH 5/5] Update packages/react/src/components/popover/popover.tsx Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- packages/react/src/components/popover/popover.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/react/src/components/popover/popover.tsx b/packages/react/src/components/popover/popover.tsx index bc6e5ce713..a795c8d752 100644 --- a/packages/react/src/components/popover/popover.tsx +++ b/packages/react/src/components/popover/popover.tsx @@ -119,7 +119,7 @@ export const Popover = forwardRef( const handleKeydown = (event: KeyboardEvent) => { if (event.key === 'Escape' && controlledOpen && isTopLayer(popover)) { event.preventDefault(); // Prevent closing fullscreen in Safari - document.querySelector(trigger)?.focus?.(); // Move focus back to trigger since `popoover="manual"` doesn't do this + document.querySelector(trigger)?.focus?.(); // Move focus back to trigger since `popover="manual"` doesn't do this setInternalOpen(false); onClose?.(); }