+
+ {/* Dropdown */}
{openDropdownIdx === i && (
{
- if (el) el.focus();
- }}
+ ref={el => { if (el) el.focus(); }}
tabIndex={0}
style={{
position: "absolute",
@@ -2852,31 +2848,13 @@ function App({ container_id, imageStacks, autoCacheStack, annotationJson, viewer
}}
role="listbox"
onMouseDown={e => e.stopPropagation()}
- onWheel={e => {
- // Trap scroll inside the dropdown
- const target = e.currentTarget as HTMLDivElement;
- const { scrollTop, scrollHeight, clientHeight } = target;
- const atTop = scrollTop === 0;
- const atBottom = scrollTop + clientHeight >= scrollHeight - 1;
- if (
- (e.deltaY < 0 && atTop) ||
- (e.deltaY > 0 && atBottom)
- ) {
- // Let the event bubble to parent (viewport)
- return;
- }
- // Otherwise, prevent scrolling the viewport
- e.stopPropagation();
- e.preventDefault();
- // Manually scroll the menu
- target.scrollTop += e.deltaY;
- }}
onBlur={e => {
- const related = e.relatedTarget as Node;
- const parent = e.currentTarget.parentElement;
- if (!parent?.contains(related)) {
- setTimeout(() => setOpenDropdownIdx(null), 100);
- }
+ // close when focus leaves
+ setTimeout(() => {
+ if (!(e.currentTarget as HTMLElement).contains(document.activeElement)) {
+ setOpenDropdownIdx(null);
+ }
+ }, 0);
}}
>
{availableStacks.map((stackObj, idx) => {
@@ -2911,14 +2889,9 @@ function App({ container_id, imageStacks, autoCacheStack, annotationJson, viewer
console.warn(`Attempted to select invalid stack at index ${idx}`, stackObj);
return;
}
- // Select the stack for this viewport
- // Use the shared handler so selection behavior is consistent
- handleLoadStack(i, idx).catch((err) => {
- console.error("Failed to load stack:", err);
- });
-
- // Close the dropdown
- setOpenDropdownIdx(null);
+ // Use existing handler to load the stack into this viewport
+ handleLoadStack(i, idx).catch(err => console.error("Failed to load stack:", err));
+ setOpenDropdownIdx(null);
}}
>
{label}
@@ -2928,718 +2901,718 @@ function App({ container_id, imageStacks, autoCacheStack, annotationJson, viewer
})}