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 });