Fix virtual scrolling MenuList font family dropdowns shrinking when wider content is unmounted (#3987)

* Fix virtual scrolling MenuList dropdowns shrinking when wider content goes away

* Code review fixes

* Fix small CI workflow bug

* Stop scrolling in dropdowns from horizontally scrolling the control bar

* Use more robust way of getting commit hash in CI workflow
This commit is contained in:
Keavon Chambers 2026-04-02 19:24:41 -07:00 committed by GitHub
parent ab822afae4
commit 5edb00bd9a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 40 additions and 4 deletions

View File

@ -162,7 +162,7 @@ jobs:
REF="master"
ENVIRONMENT="graphite-dev (Production)"
else
REF="${{ inputs.checkout_ref || github.head_ref || github.ref_name }}"
REF="$(git rev-parse HEAD)"
ENVIRONMENT="graphite-dev (Preview)"
fi
DEPLOY_ID=$(gh api \

View File

@ -47,6 +47,8 @@
let virtualScrollingEntriesStart = 0;
let keydownListenerAdded = false;
let destroyed = false;
let maxMenuWidth = 0;
let resizeObserver: ResizeObserver | undefined = undefined;
// eslint-disable-next-line svelte/prefer-svelte-reactivity -- `loadedFonts` reactivity is driven by `loadedFontsGeneration`, not the Set itself
let loadedFonts = new Set<string>();
let loadedFontsGeneration = 0;
@ -77,6 +79,7 @@
});
onDestroy(() => {
removeEventListener("keydown", keydown);
resizeObserver?.disconnect();
// Set the destroyed status in the closure kept by the awaited `tick()` in `onMount` in case that delayed run occurs after the component is destroyed
destroyed = true;
});
@ -144,6 +147,15 @@
keydownListenerAdded = false;
}
// For virtual scrolling menus, observe width changes so the menu only grows and never shrinks while open
if (open && virtualScrolling) {
startMenuWidthObserver();
} else if (resizeObserver) {
resizeObserver.disconnect();
resizeObserver = undefined;
maxMenuWidth = 0;
}
highlighted = activeEntry;
dispatch("open", open);
@ -156,14 +168,38 @@
});
}
function watchEntriesHash(_entriesHash: bigint) {
function watchEntriesHash(_: bigint) {
reactiveEntries = entries;
}
function watchRemeasureWidth(_: MenuListEntry[][], __: boolean) {
// Skip re-measurement for virtual scrolling menus since ResizeObserver handles their width
if (virtualScrolling) return;
self?.measureAndEmitNaturalWidth();
}
async function startMenuWidthObserver() {
await tick();
// Guard against the menu having closed during the tick
if (!open) return;
const floatingMenuContentDiv = self?.div()?.querySelector("[data-floating-menu-content]");
if (!(floatingMenuContentDiv instanceof HTMLElement)) return;
maxMenuWidth = 0;
resizeObserver?.disconnect();
resizeObserver = new ResizeObserver(() => {
const width = floatingMenuContentDiv.scrollWidth;
if (width > maxMenuWidth) {
maxMenuWidth = width;
floatingMenuContentDiv.style.minWidth = `${maxMenuWidth}px`;
}
});
resizeObserver.observe(floatingMenuContentDiv);
}
function onScroll(e: Event) {
if (!virtualScrollingEntryHeight) return;
virtualScrollingEntriesStart = e.target instanceof HTMLElement ? e.target.scrollTop : 0;

View File

@ -492,7 +492,7 @@
<div class="tail" bind:this={tail}></div>
{/if}
{#if displayContainer}
<div class="floating-menu-container" bind:this={floatingMenuContainer}>
<div class="floating-menu-container" bind:this={floatingMenuContainer} on:wheel|stopPropagation>
<LayoutCol class="floating-menu-content" styles={{ "min-width": minWidthStyleValue }} {scrollableY} bind:this={floatingMenuContent} data-floating-menu-content>
<slot />
</LayoutCol>

View File

@ -225,7 +225,7 @@ export function onWheelScroll(e: WheelEvent, editor: EditorWrapper) {
// Redirect vertical scroll wheel movement into a horizontal scroll on a horizontally scrollable element
// There seems to be no possible way to properly employ the browser's smooth scrolling interpolation
const horizontalScrollableElement = e.target instanceof Element && e.target.closest("[data-scrollable-x]");
const horizontalScrollableElement = e.target instanceof Element && !e.target.closest("[data-scrollable-y]") && e.target.closest("[data-scrollable-x]");
if (horizontalScrollableElement && e.deltaY !== 0) {
horizontalScrollableElement.scrollTo(horizontalScrollableElement.scrollLeft + e.deltaY, 0);
return;