fix(grid): prevent result toolbar vertical scrolling

This commit is contained in:
t8y2 2026-07-17 08:25:30 +08:00
parent 51b4c79847
commit 6193f8b860
3 changed files with 21 additions and 7 deletions

View File

@ -7375,12 +7375,13 @@ const gridContextMenuItems = computed<ContextMenuItem[]>(() => {
<CustomContextMenu :items="gridContextMenuItems" v-slot="{ onContextMenu }">
<div v-if="hasData || canShowWhereSearch" class="flex-1 flex flex-col overflow-hidden" @contextmenu="onContextMenu">
<!-- Search bar -->
<!-- Result and standalone output views must share a fixed toolbar height to prevent layout shifts. -->
<div ref="dataGridTopbarRef" v-if="showDataGridTopbar" class="data-grid-topbar-shell flex h-7 min-w-0 shrink-0 border-b bg-muted/20">
<!-- Leave real vertical space around the 28px controls instead of fitting them against the border. -->
<div ref="dataGridTopbarRef" v-if="showDataGridTopbar" class="data-grid-topbar-shell flex h-8 min-w-0 shrink-0 items-center border-b bg-muted/20">
<div v-if="hasResultToolbarLeadingSlot" class="flex shrink-0 items-center border-r">
<slot name="result-toolbar-leading" :compact="compactDataGridToolbar" />
</div>
<div class="data-grid-topbar-scroll min-w-0 flex-1 overflow-x-hidden">
<!-- Clip both axes instead of creating a hidden scroll container around the toolbar controls. -->
<div class="data-grid-topbar-scroll min-w-0 flex-1 overflow-clip">
<div class="data-grid-topbar flex items-stretch relative" :class="{ 'data-grid-topbar--compact': compactDataGridToolbar }">
<div v-if="useTransaction && editable && hasDataGridSaveTarget" class="flex items-center px-2 py-0.5 border-r shrink-0">
<Select :model-value="rowStatusFilter" @update:model-value="(value: any) => setRowStatusFilter(String(value))">

View File

@ -1054,8 +1054,8 @@ defineExpose({ focusSearch, refreshData, refreshQueryEditorCompletionCache, hand
</div>
</div>
<!-- Keep this fixed height in sync with the embedded DataGrid toolbar when switching result views. -->
<div v-if="hasQueryOutput && showStandaloneResultToolbar" ref="standaloneResultToolbarRef" class="flex h-7 shrink-0 items-center border-b bg-muted/20">
<!-- Keep this height in sync with the embedded result toolbar. -->
<div v-if="hasQueryOutput && showStandaloneResultToolbar" ref="standaloneResultToolbarRef" class="flex h-8 shrink-0 items-center border-b bg-muted/20">
<QueryResultViewSwitcher
:active-view="activeOutputView"
:can-show-result="canShowResultOutput"

View File

@ -87,12 +87,25 @@ test("embedded and standalone result toolbars share the same fixed height", () =
const standaloneClasses = contentArea.match(/ref="standaloneResultToolbarRef" class="([^"]+)"/)?.[1].split(/\s+/) ?? [];
const embeddedClasses = dataGrid.match(/ref="dataGridTopbarRef"[^>]+class="([^"]+)"/)?.[1].split(/\s+/) ?? [];
assert.ok(standaloneClasses.includes("h-7"));
assert.ok(embeddedClasses.includes("h-7"));
assert.ok(standaloneClasses.includes("h-8"));
assert.ok(embeddedClasses.includes("h-8"));
assert.ok(standaloneClasses.includes("items-center"));
assert.ok(embeddedClasses.includes("items-center"));
assert.ok(!standaloneClasses.includes("h-7"));
assert.ok(!embeddedClasses.includes("h-7"));
assert.ok(!standaloneClasses.includes("min-h-7"));
assert.ok(!embeddedClasses.includes("min-h-7"));
});
test("embedded result toolbar cannot scroll vertically", () => {
const dataGrid = source(dataGridPath);
const scrollClasses = dataGrid.match(/class="data-grid-topbar-scroll ([^"]+)"/)?.[1].split(/\s+/) ?? [];
assert.ok(scrollClasses.includes("overflow-clip"));
assert.ok(!scrollClasses.some((className) => className.startsWith("overflow-x-")));
assert.ok(!scrollClasses.some((className) => className.startsWith("overflow-y-")));
});
test("DataGrid marks toolbar refresh separately from current-result reloads", () => {
const dataGrid = source(dataGridPath);