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:
parent
ab822afae4
commit
5edb00bd9a
|
|
@ -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 \
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Reference in New Issue