From caced8664ce060d58a6ca97ca72c7b36649d3e38 Mon Sep 17 00:00:00 2001 From: npeter83 Date: Fri, 21 Aug 2026 04:00:54 +0200 Subject: [PATCH] fix(e5): stop the filter dropdown flashing at the origin before it positions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The combi-input popover flashed in the top-left corner for a frame, then jumped into place. Two causes, both confirmed with a per-frame capture in the browser: 1. The panel painted before floating-ui computed a position — gated its visibility on `isPositioned` (hidden until positioned), same as PopoverSurface. 2. The bigger one: the `popIn` entrance animation animates `transform` (scale/translateY), and it sat on the SAME element floating-ui positions via `transform` — so during the 0.16s animation the keyframes OVERRODE the translate(x,y) and the panel rendered at the origin. Moved the glass styling + popIn onto an inner child, leaving the positioned element's transform untouched. Frame capture after the fix: frame 0 hidden, first visible frame already at translate(82,474) — never visible at the origin. Also gave the size middleware a min width for a narrow rail. --- frontend/src/components/MultiSelectChips.tsx | 25 ++++++++++++-------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/frontend/src/components/MultiSelectChips.tsx b/frontend/src/components/MultiSelectChips.tsx index 0796d816..343794a3 100644 --- a/frontend/src/components/MultiSelectChips.tsx +++ b/frontend/src/components/MultiSelectChips.tsx @@ -51,7 +51,7 @@ export default function MultiSelectChips({ const inputRef = useRef(null); const fade = useScrollFade(); - const { refs, floatingStyles, context } = useFloating({ + const { refs, floatingStyles, context, isPositioned } = useFloating({ open, onOpenChange: setOpen, placement: "bottom-start", @@ -62,12 +62,10 @@ export default function MultiSelectChips({ shift({ padding: 8 }), size({ padding: 8, - apply({ rects, elements, availableHeight }) { - // Match the field width and cap to the space below (or 320px, whichever is smaller). - Object.assign(elements.floating.style, { - width: `${rects.reference.width}px`, - maxHeight: `${Math.min(availableHeight, 320)}px`, - }); + apply({ rects, elements }) { + // Match the field width (with a sane minimum for a very narrow rail); the inner scroll box + // owns the height cap (max-h-64). + elements.floating.style.width = `${Math.max(rects.reference.width, 192)}px`; }, }), ], @@ -166,15 +164,22 @@ export default function MultiSelectChips({