From 408763c8ab45a5d9189e1b1b8b8990b7da8bce74 Mon Sep 17 00:00:00 2001
From: Connor Lanigan
Date: Tue, 15 Apr 2025 13:57:53 +0200
Subject: [PATCH] fix: Popover is positioned incorrectly when the layout
changes
---
src/popover/container.tsx | 20 ++++++++++++++------
1 file changed, 14 insertions(+), 6 deletions(-)
diff --git a/src/popover/container.tsx b/src/popover/container.tsx
index b5d3744a8d..0c8b41d394 100644
--- a/src/popover/container.tsx
+++ b/src/popover/container.tsx
@@ -99,11 +99,11 @@ export default function PopoverContainer({
/*
This is a heuristic. Some layout changes are caused by user clicks (e.g. toggling the tools panel, submitting a form),
and by tracking the click event we can adapt the popover's position to the new layout.
-
- TODO: extend this to Enter and Spacebar?
*/
- const onClick = (event: UIEvent | KeyboardEvent) => {
+ const controller = new AbortController();
+
+ const onClick = async (event: UIEvent | KeyboardEvent) => {
if (
// Do not update position if keepPosition is true.
keepPosition ||
@@ -114,14 +114,22 @@ export default function PopoverContainer({
return;
}
- requestAnimationFrame(() => {
+ // Continuously update the popover position for one second to account for any layout changes
+ // and animations. This runs only while the CPU is otherwise idle.
+ const targetTime = performance.now() + 1_000;
+
+ while (performance.now() < targetTime) {
+ if (controller.signal.aborted) {
+ break;
+ }
+
updatePositionHandler();
- });
+ await new Promise(r => requestIdleCallback(r));
+ }
};
const updatePositionOnResize = () => requestAnimationFrame(() => updatePositionHandler());
const refreshPosition = () => requestAnimationFrame(() => positionHandlerRef.current());
- const controller = new AbortController();
window.addEventListener('click', onClick, { signal: controller.signal });
window.addEventListener('resize', updatePositionOnResize, { signal: controller.signal });