From 32a4821cb44903e1b519a6199f2064f04b53df39 Mon Sep 17 00:00:00 2001 From: iris Date: Sun, 25 Oct 2026 17:19:51 +0100 Subject: [PATCH] swarm-ui: an open dropdown closes only on a scroll that moves it --- .../packages/swarm-ui/src/ui/select-field/Listbox.tsx | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/frontend/packages/swarm-ui/src/ui/select-field/Listbox.tsx b/frontend/packages/swarm-ui/src/ui/select-field/Listbox.tsx index df5d3401..9b3f528a 100644 --- a/frontend/packages/swarm-ui/src/ui/select-field/Listbox.tsx +++ b/frontend/packages/swarm-ui/src/ui/select-field/Listbox.tsx @@ -15,8 +15,8 @@ // layer: it is not clipped by a scrolling ancestor, and inside a modal // `` it shows above the dialog (it is a descendant of the control, so // the dialog's inertness leaves it alone). `position: fixed` coordinates come -// from the control's box (`placePopup`). A scroll or resize elsewhere, or a -// click outside, closes it, as a native select's list closes. +// from the control's box (`placePopup`). A scroll that moves the control, a +// resize, or a click outside closes it, as a native select's list closes. // // Not a native control, so there is no form validation: `required` is only // `aria-required`, and a caller that needs a choice checks it itself. @@ -129,8 +129,11 @@ export function Listbox({ if (!triggerRef.current?.contains(t) && !listRef.current?.contains(t)) closeList(); } + // Only a scroll that moves the control closes it: the page, or a box the + // control sits in. A live terminal scrolling itself elsewhere on the page + // must not shut it under the pointer. function onScroll(e: Event) { - if (!listRef.current?.contains(e.target as Node)) closeList(); + if ((e.target as Node).contains(triggerRef.current)) closeList(); } document.addEventListener("pointerdown", onPointerDown); window.addEventListener("scroll", onScroll, true);