feat(grid): configure cell detail button visibility

Closes #5593
This commit is contained in:
t8y2 committed 2026-08-24 19:54:35 +00:00
1 parent 3232195e1f
commit 68b0ab0476
17 files changed
+146 -9

No files matched your search

@@ -362,6 +362,7 @@ const slots = useSlots();
const connectionStore = useConnectionStore();
const queryStore = useQueryStore();
const settingsStore = useSettingsStore();
const cellDetailButtonEnabled = computed(() => settingsStore.editorSettings.dataGridCellDetailButtonVisible);
const tableFontSize = computed(() => settingsStore.editorSettings.tableFontSize);
const rowNumberWidth = ref(DATA_GRID_ROW_NUM_WIDTH);
const largeValueResolutionVersion = ref(0);
@@ -7296,7 +7297,8 @@ const canvasDetailButtonCell = computed(() => {
const visibleRight = viewportWidth > 0 ? Math.min(viewportWidth, rect.left + rect.width) : rect.left + rect.width;
const canQuickDownload = canQuickDownloadCellValue(target.rowIndex, target.col);
const foreignKey = canvasCellForeignKey(target.rowIndex, target.col);
const minWidth = canvasDataGridActionOverlayWidth(canQuickDownload, !!foreignKey) + 2;
if (!cellDetailButtonEnabled.value && !canQuickDownload && !foreignKey) return null;
const minWidth = canvasDataGridActionOverlayWidth(canQuickDownload, !!foreignKey, cellDetailButtonEnabled.value) + 2;
if (rect.top < 0 || rect.top > viewportHeight - 1 || visibleRight - visibleLeft < minWidth) return null;
return {
rowIndex: target.rowIndex,
@@ -7311,7 +7313,7 @@ const canvasDetailButtonCell = computed(() => {
const canvasDetailButtonStyle = computed(() => {
const cell = canvasDetailButtonCell.value;
if (!cell) return {};
const actionWidth = canvasDataGridActionOverlayWidth(cell.canQuickDownload, !!cell.foreignKey);
const actionWidth = canvasDataGridActionOverlayWidth(cell.canQuickDownload, !!cell.foreignKey, cellDetailButtonEnabled.value);
const edgeGap = 6;
return {
left: `${Math.max(rowNumberWidth.value, cell.rect.left + cell.rect.width - actionWidth - edgeGap)}px`,
@@ -7325,7 +7327,7 @@ const canvasRightAlignedActionCell = computed(() => {
return {
rowIndex: cell.rowIndex,
visibleColIdx: cell.visibleColIdx,
reservedWidth: canvasDataGridActionReservedWidth(cell.canQuickDownload, !!cell.foreignKey),
reservedWidth: canvasDataGridActionReservedWidth(cell.canQuickDownload, !!cell.foreignKey, cellDetailButtonEnabled.value),
};
});
@@ -7412,6 +7414,7 @@ watch(
hoveredDetailCell,
detailCell,
showCellDetail,
cellDetailButtonEnabled,
editingCell,
frozenColumnCount,
saveError,
@@ -12083,6 +12086,7 @@ function currentGridContextMenuItems(): ContextMenuItem[] {
</template>
</LightDropdownMenu>
<button
v-if="cellDetailButtonEnabled"
class="flex h-5 w-5 items-center justify-center rounded bg-background/90 text-muted-foreground shadow-sm ring-1 ring-border hover:text-foreground"
:title="t('grid.cellDetails')"
@mousedown.stop
@@ -12816,6 +12820,7 @@ function currentGridContextMenuItems(): ContextMenuItem[] {
<ArrowUpRight class="h-3 w-3" />
</button>
<button
v-if="cellDetailButtonEnabled"
class="flex h-5 w-5 items-center justify-center rounded bg-background/90 text-muted-foreground shadow-sm ring-1 ring-border hover:text-foreground"
:title="t('grid.cellDetails')"
@mousedown.stop
@@ -13031,6 +13036,7 @@ function currentGridContextMenuItems(): ContextMenuItem[] {
</template>
</LightDropdownMenu>
<button
v-if="cellDetailButtonEnabled"
class="flex h-5 w-5 items-center justify-center rounded bg-background/90 text-muted-foreground shadow-sm ring-1 ring-border hover:text-foreground"
:title="t('grid.cellDetails')"
@mousedown.stop
@@ -4,6 +4,29 @@ import { describe, expect, it } from "vitest";
const dataGridSource = readFileSync(new URL("../DataGrid.vue", import.meta.url), "utf8");
describe("DataGrid cell detail selection", () => {
it("gates only the three hover Info buttons with the visibility setting", () => {
expect(dataGridSource).toContain("const cellDetailButtonEnabled = computed(() => settingsStore.editorSettings.dataGridCellDetailButtonVisible);");
expect(dataGridSource.match(/v-if="cellDetailButtonEnabled"/g)).toHaveLength(3);
expect(dataGridSource.match(/v-if="cellDetailButtonVisible\(/g)).toHaveLength(2);
const hoverVisibility = dataGridSource.match(/function cellDetailButtonVisible[\s\S]*?\n\}/)?.[0];
expect(hoverVisibility).toBeDefined();
expect(hoverVisibility).not.toContain("dataGridCellDetailButtonVisible");
});
it("removes the Canvas action overlay and reservation only when no action remains", () => {
expect(dataGridSource).toContain("if (!cellDetailButtonEnabled.value && !canQuickDownload && !foreignKey) return null;");
expect(dataGridSource).toContain("canvasDataGridActionOverlayWidth(canQuickDownload, !!foreignKey, cellDetailButtonEnabled.value)");
expect(dataGridSource).toContain("canvasDataGridActionOverlayWidth(cell.canQuickDownload, !!cell.foreignKey, cellDetailButtonEnabled.value)");
expect(dataGridSource).toContain("canvasDataGridActionReservedWidth(cell.canQuickDownload, !!cell.foreignKey, cellDetailButtonEnabled.value)");
expect(dataGridSource).toMatch(/watch\([\s\S]*?cellDetailButtonEnabled,[\s\S]*?scheduleCanvasDraw/);
});
it("keeps context-menu details and refresh restoration independent of the hover setting", () => {
expect(dataGridSource).toContain("cellDetails: openContextCellDetailDialog");
expect(dataGridSource).toContain("if (cellDialog) openCellDetailDialog(cellDialog.rowIndex, cellDialog.col);");
});
it("resynchronizes the open detail after a mouse selection gesture finishes", () => {
expect(dataGridSource).toContain("watch([selectedRange, showCellDetail, isEditingDetail, isSelectingCells]");
expect(dataGridSource).toContain("if (isSelectingCells.value) return;");