feat(table): add table font size control (#2095)

This commit is contained in:
zipg authored and GitHub committed 2026-06-30 01:57:14 +08:00
1 parent c04203ca90
commit a458ebd08f
6 files changed
+125 -19

No files matched your search

+25 -15
View File
@@ -164,6 +164,7 @@ const slots = useSlots();
const connectionStore = useConnectionStore();
const queryStore = useQueryStore();
const settingsStore = useSettingsStore();
const tableFontSize = computed(() => settingsStore.editorSettings.tableFontSize);
const { isDark } = useTheme();
const { toast } = useToast();
const { highlight } = useSqlHighlighter();
@@ -2062,6 +2063,7 @@ const gridStyle = computed(() => ({
"--header-total-w": dataGridHeaderContentWidth("var(--total-w)", gridScrollbarGutter.value),
"--grid-scrollbar-gutter": `${gridScrollbarGutter.value}px`,
[EDITOR_FONT_FAMILY_CSS_VAR]: settingsStore.editorSettings.fontFamily,
"--dbx-table-font-size": `${tableFontSize.value}px`,
}));
const gridHorizontalScrollLeft = ref(0);
const gridViewportWidth = ref(0);
@@ -4436,7 +4438,7 @@ const canvasSurfaceWidth = computed(() => {
if (vw <= 0) return total;
return Math.min(vw, total);
});
const canvasRenderStyleKey = computed(() => `${settingsStore.editorSettings.theme}:${settingsStore.editorSettings.uiScale}:${canvasBackingPixelRatio.value}:${isDark.value}:${settingsStore.editorSettings.fontFamily}`);
const canvasRenderStyleKey = computed(() => `${settingsStore.editorSettings.theme}:${settingsStore.editorSettings.uiScale}:${canvasBackingPixelRatio.value}:${isDark.value}:${settingsStore.editorSettings.fontFamily}:${tableFontSize.value}`);
const CANVAS_MOUSE_WHEEL_SCROLL_MULTIPLIER = 1.5;
const CANVAS_TRACKPAD_DELTA_THRESHOLD = 40;
let canvasResizeObserver: ResizeObserver | null = null;
@@ -7698,7 +7700,7 @@ const gridContextMenuItems = computed<ContextMenuItem[]>(() => {
@scroll="onTransposeScroll"
>
<template #before>
<div class="sticky top-0 z-20 flex h-7 border-b border-border bg-[rgb(239_239_239)] text-xs font-semibold text-muted-foreground dark:bg-muted" :style="{ width: `${transposeTotalWidth}px` }">
<div class="data-grid-transpose-header sticky top-0 z-20 flex h-7 border-b border-border bg-[rgb(239_239_239)] font-semibold text-muted-foreground dark:bg-muted" :style="{ width: `${transposeTotalWidth}px` }">
<div class="sticky left-0 z-30 shrink-0 border-r border-border px-3 py-1.5 bg-[rgb(239_239_239)] truncate dark:bg-muted relative" :style="{ width: `${transposePinnedWidth}px` }">
{{ t("grid.columnName") }}
<div class="absolute right-0 top-0 bottom-0 w-1.5 cursor-col-resize hover:bg-primary/30" @mousedown.stop="onTransposePinnedResizeStart" />
@@ -7724,7 +7726,7 @@ const gridContextMenuItems = computed<ContextMenuItem[]>(() => {
</div>
</template>
<template #default="{ item }">
<div class="flex border-b border-border/60 text-xs" :style="{ height: '30px', width: `${transposeTotalWidth}px` }">
<div class="data-grid-transpose-row flex border-b border-border/60" :style="{ height: '30px', width: `${transposeTotalWidth}px` }">
<div class="sticky left-0 z-10 flex shrink-0 items-center border-r border-border bg-background px-3 py-0 font-medium truncate" :style="{ width: `${transposePinnedWidth}px` }" :title="item.column">
{{ item.column }}
</div>
@@ -7765,7 +7767,7 @@ const gridContextMenuItems = computed<ContextMenuItem[]>(() => {
autocapitalize="off"
autocorrect="off"
spellcheck="false"
class="cell-edit-input cell-edit-input--expanded absolute left-0 top-0 min-h-full bg-background px-1.5 py-1 text-[13px] leading-[18px] outline-none z-10"
class="cell-edit-input cell-edit-input--expanded absolute left-0 top-0 min-h-full bg-background px-1.5 py-1 leading-[18px] outline-none z-10"
@blur="commitEditFromBlur"
@click.stop
@focus="onCellEditTextareaInput"
@@ -7780,7 +7782,7 @@ const gridContextMenuItems = computed<ContextMenuItem[]>(() => {
autocapitalize="off"
autocorrect="off"
spellcheck="false"
class="cell-edit-input absolute inset-0 bg-background border-2 border-primary px-1.5 py-0 text-[13px] leading-[26px] outline-none z-10"
class="cell-edit-input absolute inset-0 bg-background border-2 border-primary px-1.5 py-0 leading-[26px] outline-none z-10"
@blur="commitEditFromBlur"
@click.stop
@input="onCellEditTextareaInput"
@@ -7826,7 +7828,7 @@ const gridContextMenuItems = computed<ContextMenuItem[]>(() => {
<template v-else>
<!-- Sticky header -->
<div ref="headerRef" class="shrink-0 bg-[rgb(239_239_239)] dark:bg-muted/60 z-10 w-full border-y border-border overflow-hidden">
<div class="flex w-(--header-total-w) text-xs font-semibold text-foreground">
<div class="data-grid-header-row flex w-(--header-total-w) font-semibold text-foreground">
<div
class="shrink-0 px-2 py-1.5 border-r w-(--row-num-w) border-border text-center text-muted-foreground select-none cursor-default hover:bg-gray-200 dark:hover:bg-gray-800 sticky left-0 z-20 bg-[rgb(239_239_239)] dark:bg-muted"
:class="{ '!bg-gray-300 dark:!bg-gray-900 outline outline-primary -outline-offset-1': isSelectingAll }"
@@ -8195,7 +8197,7 @@ const gridContextMenuItems = computed<ContextMenuItem[]>(() => {
<div class="relative" :style="{ width: `${totalWidth}px`, height: `${canvasContentHeight}px` }">
<canvas
ref="canvasRef"
class="canvas-grid-surface dbx-data-grid-font-family sticky left-0 top-0 z-0 block text-[13px]/[1rem] font-normal"
class="canvas-grid-surface dbx-data-grid-font-family sticky left-0 top-0 z-0 block font-normal"
:style="{ width: `${canvasSurfaceWidth}px`, height: `${canvasViewportHeight}px` }"
@mousemove="onCanvasMouseMove"
@mouseleave="onCanvasMouseLeave"
@@ -8223,7 +8225,7 @@ const gridContextMenuItems = computed<ContextMenuItem[]>(() => {
autocapitalize="off"
autocorrect="off"
spellcheck="false"
class="cell-edit-input cell-edit-input--expanded absolute left-0 top-0 min-h-full bg-background px-2.5 py-1 text-[13px] leading-[18px] outline-none z-10"
class="cell-edit-input cell-edit-input--expanded absolute left-0 top-0 min-h-full bg-background px-2.5 py-1 leading-[18px] outline-none z-10"
@blur="commitEditFromBlur"
@click.stop
@focus="onCellEditTextareaInput"
@@ -8238,7 +8240,7 @@ const gridContextMenuItems = computed<ContextMenuItem[]>(() => {
autocapitalize="off"
autocorrect="off"
spellcheck="false"
class="cell-edit-input absolute inset-0 bg-background border-2 border-primary px-2.5 py-0 text-[13px] leading-[22px] outline-none z-10"
class="cell-edit-input absolute inset-0 bg-background border-2 border-primary px-2.5 py-0 leading-[22px] outline-none z-10"
@blur="commitEditFromBlur"
@click.stop
@input="onCellEditTextareaInput"
@@ -8285,7 +8287,7 @@ const gridContextMenuItems = computed<ContextMenuItem[]>(() => {
<RecycleScroller
v-else-if="hasVisibleRows"
ref="scrollerRef"
class="data-grid-scroller dbx-data-grid-font-family flex-1 overflow-x-auto overscroll-none text-[13px]"
class="data-grid-scroller dbx-data-grid-font-family flex-1 overflow-x-auto overscroll-none"
:class="{ 'is-scrolling': isScrolling }"
:items="displayItems"
:item-size="26"
@@ -8296,7 +8298,7 @@ const gridContextMenuItems = computed<ContextMenuItem[]>(() => {
>
<template #default="{ item }">
<div
class="flex text-[13px] border-b border-border h-6.5 w-(--total-w)"
class="data-grid-row flex border-b border-border h-6.5 w-(--total-w)"
:class="{
'bg-destructive/5 opacity-70': item.isDeleted,
'bg-primary/5': item.isNew && !isRowActive(item.displayIndex),
@@ -8319,7 +8321,7 @@ const gridContextMenuItems = computed<ContextMenuItem[]>(() => {
<div
v-for="col in renderedGridColumns"
:key="col.actualColIdx"
class="group/cell shrink-0 px-3 py-1 border-r border-border whitespace-nowrap overflow-hidden text-ellipsis relative select-none inline-block items-center tabular-nums text-[13px]"
class="data-grid-cell group/cell shrink-0 px-3 py-1 border-r border-border whitespace-nowrap overflow-hidden text-ellipsis relative select-none inline-block items-center tabular-nums"
:style="renderedColumnStyle(col.visibleColIdx)"
:class="{
'text-muted-foreground italic': isNull(item.data[col.actualColIdx]),
@@ -8355,7 +8357,7 @@ const gridContextMenuItems = computed<ContextMenuItem[]>(() => {
autocapitalize="off"
autocorrect="off"
spellcheck="false"
class="cell-edit-input cell-edit-input--expanded absolute left-0 top-0 min-h-full bg-background px-2.5 py-1 text-[13px] leading-[18px] outline-none z-10"
class="cell-edit-input cell-edit-input--expanded absolute left-0 top-0 min-h-full bg-background px-2.5 py-1 leading-[18px] outline-none z-10"
@blur="commitEditFromBlur"
@click.stop
@focus="onCellEditTextareaInput"
@@ -8370,7 +8372,7 @@ const gridContextMenuItems = computed<ContextMenuItem[]>(() => {
autocapitalize="off"
autocorrect="off"
spellcheck="false"
class="cell-edit-input absolute inset-0 bg-background border-2 border-primary px-2.5 py-0 text-[13px] leading-[22px] outline-none z-10"
class="cell-edit-input absolute inset-0 bg-background border-2 border-primary px-2.5 py-0 leading-[22px] outline-none z-10"
@blur="commitEditFromBlur"
@click.stop
@input="onCellEditTextareaInput"
@@ -9449,6 +9451,13 @@ const gridContextMenuItems = computed<ContextMenuItem[]>(() => {
margin-inline-end: 0.25rem;
}
.data-grid-scroller,
.data-grid-header-row,
.data-grid-transpose-header,
.data-grid-transpose-row {
font-size: var(--dbx-table-font-size, 13px);
}
.data-grid-topbar-action-button--compact .data-grid-topbar-action-icon {
margin-inline-end: 0;
transform: scale(0.96);
@@ -9589,7 +9598,7 @@ const gridContextMenuItems = computed<ContextMenuItem[]>(() => {
.canvas-grid-surface {
cursor: cell;
font-family: var(--dbx-data-grid-font-family);
font-size: 13px;
font-size: var(--dbx-table-font-size, 13px);
font-weight: 400;
line-height: 1rem;
outline: none;
@@ -9597,6 +9606,7 @@ const gridContextMenuItems = computed<ContextMenuItem[]>(() => {
.cell-edit-input {
font-family: inherit;
font-size: var(--dbx-table-font-size, 13px);
}
.cell-edit-input--expanded {
@@ -3,7 +3,7 @@ import { computed, ref, defineAsyncComponent, watch, nextTick, onMounted, onUnmo
import { safeLocalStorageGet, safeLocalStorageSet } from "@/lib/safeStorage";
import type { CSSProperties } from "vue";
import { useI18n } from "vue-i18n";
import { Check, Columns3, EyeOff, Loader2, Search, Bot, GitBranch, BarChart3, TableProperties, ChevronDown, ChevronUp, Inbox, RefreshCcw, Wrench, Toolbox, ListChecks, Database, FileUp, Download, X, Pin, Rows3, SquareDashed } from "@lucide/vue";
import { Check, Columns3, EyeOff, Loader2, Search, Bot, GitBranch, BarChart3, TableProperties, ChevronDown, ChevronUp, Inbox, RefreshCcw, Wrench, Toolbox, ListChecks, Database, FileUp, Download, X, Pin, Rows3, SquareDashed, Minus, Plus } from "@lucide/vue";
import { Splitpanes, Pane } from "splitpanes";
import "splitpanes/dist/splitpanes.css";
import { Button } from "@/components/ui/button";
@@ -49,7 +49,7 @@ const ExplainPlanViewer = defineAsyncComponent(() => import("@/components/explai
const QueryChart = defineAsyncComponent(() => import("@/components/chart/QueryChart.vue"));
import { useQueryStore } from "@/stores/queryStore";
import { useConnectionStore } from "@/stores/connectionStore";
import { useSettingsStore } from "@/stores/settingsStore";
import { TABLE_FONT_SIZE_DEFAULT, TABLE_FONT_SIZE_MAX, TABLE_FONT_SIZE_MIN, useSettingsStore } from "@/stores/settingsStore";
import { useToast } from "@/composables/useToast";
import { canCancelQueryExecution, queryExecutionLabelKey } from "@/lib/queryExecutionState";
import { databaseDisplayNameForTab, executionSummaryItems, nextExecutionSummaryView, resultGridCacheKey, resultRunItems, tabularResultItems } from "@/lib/tabPresentation";
@@ -175,6 +175,8 @@ const resultTabsScrollerRef = ref<HTMLElement | null>(null);
const columnVisibilitySearch = ref("");
const columnVisibilityOptions = computed(() => dataGridRef.value?.filteredColumnVisibilityOptions(columnVisibilitySearch.value) ?? []);
const dataGridRenderMode = computed(() => settingsStore.editorSettings.dataGridRenderMode);
const tableFontSize = computed(() => settingsStore.editorSettings.tableFontSize);
const dataGridViewOptionsActive = computed(() => dataGridRef.value?.nullColumnsHidden || dataGridRef.value?.multiRowTranspose || dataGridRenderMode.value === "dom" || tableFontSize.value !== TABLE_FONT_SIZE_DEFAULT);
const redisKeyBrowserRef = ref<SearchableBrowserHandle>();
const etcdKeyBrowserRef = ref<SearchableBrowserHandle>();
const zookeeperKeyBrowserRef = ref<SearchableBrowserHandle>();
@@ -198,6 +200,18 @@ function setDataGridRenderMode(value: "canvas" | "dom") {
settingsStore.updateEditorSettings({ dataGridRenderMode: value });
}
function setTableFontSize(value: number) {
settingsStore.updateEditorSettings({ tableFontSize: value });
}
function decreaseTableFontSize() {
setTableFontSize(tableFontSize.value - 1);
}
function increaseTableFontSize() {
setTableFontSize(tableFontSize.value + 1);
}
const activeTabDimension = computed(() => {
const tab = props.activeTab;
if (!tab.connectionId || tab.mode !== "vector") return undefined;
@@ -770,7 +784,7 @@ defineExpose({ focusSearch, refreshData, handleModRTarget, requestQueryEditorExe
size="icon"
class="h-6 w-7 shrink-0 text-foreground hover:bg-accent"
:class="{
'bg-accent text-foreground': dataGridRef?.nullColumnsHidden || dataGridRef?.multiRowTranspose || dataGridRenderMode === 'dom',
'bg-accent text-foreground': dataGridViewOptionsActive,
}"
:title="t('grid.viewOptions')"
:aria-label="t('grid.viewOptions')"
@@ -808,6 +822,33 @@ defineExpose({ focusSearch, refreshData, handleModRTarget, requestQueryEditorExe
</div>
</LightTooltip>
</div>
<div class="flex items-center justify-between gap-3 px-3 py-2 text-xs">
<div class="min-w-0 flex items-center gap-2 font-medium">
<span class="flex h-3.5 w-3.5 shrink-0 items-center justify-center text-[11px] font-semibold text-muted-foreground">A</span>
<span>{{ t("grid.tableFontSize") }}</span>
</div>
<div class="flex h-7 w-32 items-center rounded-md border bg-muted/40 p-0.5">
<button
type="button"
class="flex h-6 w-8 items-center justify-center rounded-[5px] bg-background text-foreground shadow-sm transition-colors hover:text-foreground disabled:pointer-events-none disabled:bg-muted/40 disabled:text-muted-foreground disabled:opacity-50 disabled:shadow-none"
:disabled="tableFontSize <= TABLE_FONT_SIZE_MIN"
:aria-label="t('common.decrease')"
@click="decreaseTableFontSize"
>
<Minus class="h-3.5 w-3.5" />
</button>
<span class="flex-1 text-center text-xs font-semibold tabular-nums">{{ tableFontSize }}</span>
<button
type="button"
class="flex h-6 w-8 items-center justify-center rounded-[5px] bg-background text-foreground shadow-sm transition-colors hover:text-foreground disabled:pointer-events-none disabled:bg-muted/40 disabled:text-muted-foreground disabled:opacity-50 disabled:shadow-none"
:disabled="tableFontSize >= TABLE_FONT_SIZE_MAX"
:aria-label="t('common.increase')"
@click="increaseTableFontSize"
>
<Plus class="h-3.5 w-3.5" />
</button>
</div>
</div>
<div class="flex items-center justify-between gap-3 px-3 py-2 text-xs">
<div class="min-w-0 flex items-center gap-2 font-medium">
<Rows3 class="h-3.5 w-3.5 shrink-0 text-muted-foreground" />
@@ -1062,7 +1103,7 @@ defineExpose({ focusSearch, refreshData, handleModRTarget, requestQueryEditorExe
size="icon"
class="h-6 w-7 shrink-0 text-foreground hover:bg-accent"
:class="{
'bg-accent text-foreground': dataGridRef?.nullColumnsHidden || dataGridRef?.multiRowTranspose || dataGridRenderMode === 'dom',
'bg-accent text-foreground': dataGridViewOptionsActive,
}"
:title="t('grid.viewOptions')"
:aria-label="t('grid.viewOptions')"
@@ -1100,6 +1141,33 @@ defineExpose({ focusSearch, refreshData, handleModRTarget, requestQueryEditorExe
</div>
</LightTooltip>
</div>
<div class="flex items-center justify-between gap-3 px-3 py-2 text-xs">
<div class="min-w-0 flex items-center gap-2 font-medium">
<span class="flex h-3.5 w-3.5 shrink-0 items-center justify-center text-[11px] font-semibold text-muted-foreground">A</span>
<span>{{ t("grid.tableFontSize") }}</span>
</div>
<div class="flex h-7 w-32 items-center rounded-md border bg-muted/40 p-0.5">
<button
type="button"
class="flex h-6 w-8 items-center justify-center rounded-[5px] bg-background text-foreground shadow-sm transition-colors hover:text-foreground disabled:pointer-events-none disabled:bg-muted/40 disabled:text-muted-foreground disabled:opacity-50 disabled:shadow-none"
:disabled="tableFontSize <= TABLE_FONT_SIZE_MIN"
:aria-label="t('common.decrease')"
@click="decreaseTableFontSize"
>
<Minus class="h-3.5 w-3.5" />
</button>
<span class="flex-1 text-center text-xs font-semibold tabular-nums">{{ tableFontSize }}</span>
<button
type="button"
class="flex h-6 w-8 items-center justify-center rounded-[5px] bg-background text-foreground shadow-sm transition-colors hover:text-foreground disabled:pointer-events-none disabled:bg-muted/40 disabled:text-muted-foreground disabled:opacity-50 disabled:shadow-none"
:disabled="tableFontSize >= TABLE_FONT_SIZE_MAX"
:aria-label="t('common.increase')"
@click="increaseTableFontSize"
>
<Plus class="h-3.5 w-3.5" />
</button>
</div>
</div>
<div class="flex items-center justify-between gap-3 px-3 py-2 text-xs">
<div class="min-w-0 flex items-center gap-2 font-medium">
<Rows3 class="h-3.5 w-3.5 shrink-0 text-muted-foreground" />