openTable(table.name)}
+ onDoubleClick={() => openTableByDefaultAction(table.name)}
onContextMenu={isV2Ui ? (event) => openV2OverviewContextMenu(event, table) : undefined}
style={{
background: cardBg,
@@ -1059,7 +1084,7 @@ const TableOverview: React.FC
= ({ tab }) => {
const content = (
openTable(table.name)}
+ onDoubleClick={() => openTableByDefaultAction(table.name)}
onContextMenu={isV2Ui ? (event) => openV2OverviewContextMenu(event, table) : undefined}
style={{
position: 'relative',
diff --git a/frontend/src/components/sidebar/useSidebarSearchModel.tsx b/frontend/src/components/sidebar/useSidebarSearchModel.tsx
index bdbb9c6..aa2871f 100644
--- a/frontend/src/components/sidebar/useSidebarSearchModel.tsx
+++ b/frontend/src/components/sidebar/useSidebarSearchModel.tsx
@@ -32,7 +32,6 @@ import {
import type { SearchScope } from '../sidebarCoreUtils';
import {
buildV2CommandSearchTreeIndex,
- V2_TREE_HORIZONTAL_SCROLL_BOTTOM_RESERVE,
estimateV2TreeHorizontalScrollWidth,
filterV2CommandSearchTreeItems,
filterV2ExplorerTreeByKind,
@@ -612,9 +611,7 @@ export const useSidebarSearchModel = ({
() => estimateV2TreeHorizontalScrollWidth(v2VisibleTreeData, treeViewportWidth),
[treeViewportWidth, v2VisibleTreeData],
);
- const effectiveTreeHeight = isV2Ui && v2TreeHorizontalScrollWidth
- ? Math.max(1, treeHeight - V2_TREE_HORIZONTAL_SCROLL_BOTTOM_RESERVE)
- : treeHeight;
+ const effectiveTreeHeight = treeHeight;
const v2TreeMetrics = useMemo(() => {
const databaseTableCounts = new Map();
const objectGroupCounts = new Map();
diff --git a/frontend/src/store.test.ts b/frontend/src/store.test.ts
index 30b5506..3297998 100644
--- a/frontend/src/store.test.ts
+++ b/frontend/src/store.test.ts
@@ -69,6 +69,7 @@ describe('store appearance persistence', () => {
expect(appearance.opacity).toBe(0.75);
expect(appearance.blur).toBe(6);
expect(appearance.useNativeMacWindowControls).toBe(true);
+ expect(appearance.tableDoubleClickAction).toBe('open-data');
expect(appearance.v2SidebarSearchMode).toBe('command');
expect(appearance.v2CommandSearchPersistentFilterEnabled).toBe(false);
expect(appearance.v2SidebarPersistedFilter).toBe('');
@@ -93,11 +94,13 @@ describe('store appearance persistence', () => {
useStore.getState().setAppearance({
showDataTableVerticalBorders: true,
dataTableDensity: 'compact',
+ tableDoubleClickAction: 'open-design',
});
const persisted = JSON.parse(storage.getItem('lite-db-storage') || '{}');
expect(persisted.state.appearance.showDataTableVerticalBorders).toBe(true);
expect(persisted.state.appearance.dataTableDensity).toBe('compact');
+ expect(persisted.state.appearance.tableDoubleClickAction).toBe('open-design');
vi.resetModules();
const reloaded = await importStore();
@@ -105,6 +108,21 @@ describe('store appearance persistence', () => {
expect(appearance.showDataTableVerticalBorders).toBe(true);
expect(appearance.dataTableDensity).toBe('compact');
+ expect(appearance.tableDoubleClickAction).toBe('open-design');
+ });
+
+ it('sanitizes invalid table double-click appearance settings', async () => {
+ storage.setItem('lite-db-storage', JSON.stringify({
+ state: {
+ appearance: {
+ tableDoubleClickAction: 'open-random',
+ },
+ },
+ version: 10,
+ }));
+
+ const { useStore } = await importStore();
+ expect(useStore.getState().appearance.tableDoubleClickAction).toBe('open-data');
});
it('persists language preference and sanitizes unsupported persisted values', async () => {
diff --git a/frontend/src/store.ts b/frontend/src/store.ts
index 57e8ace..1164ba0 100644
--- a/frontend/src/store.ts
+++ b/frontend/src/store.ts
@@ -79,12 +79,15 @@ import {
resolveConnectionProtectionConfig,
} from "./utils/connectionReadOnly";
+export type TableDoubleClickAction = "open-data" | "open-design";
+
export interface AppearanceSettings extends DataGridDisplaySettings {
uiVersion: "legacy" | "v2";
enabled: boolean;
opacity: number;
blur: number;
useNativeMacWindowControls: boolean;
+ tableDoubleClickAction: TableDoubleClickAction;
v2SidebarSearchMode: "command" | "filter";
v2CommandSearchPersistentFilterEnabled: boolean;
v2SidebarPersistedFilter: string;
@@ -100,6 +103,7 @@ export const DEFAULT_APPEARANCE: AppearanceSettings = {
opacity: 1.0,
blur: 0,
useNativeMacWindowControls: false,
+ tableDoubleClickAction: "open-data",
v2SidebarSearchMode: "command",
v2CommandSearchPersistentFilterEnabled: false,
v2SidebarPersistedFilter: "",
@@ -126,6 +130,12 @@ const sanitizeV2SidebarSearchMode = (
return value === "filter" ? "filter" : DEFAULT_APPEARANCE.v2SidebarSearchMode;
};
+const sanitizeTableDoubleClickAction = (
+ value: unknown,
+): TableDoubleClickAction => {
+ return value === "open-design" ? "open-design" : DEFAULT_APPEARANCE.tableDoubleClickAction;
+};
+
const sanitizeV2SidebarPersistedFilter = (value: unknown): string => {
if (typeof value !== "string") {
return DEFAULT_APPEARANCE.v2SidebarPersistedFilter;
@@ -2062,6 +2072,9 @@ const sanitizeAppearance = (
typeof appearance.useNativeMacWindowControls === "boolean"
? appearance.useNativeMacWindowControls
: DEFAULT_APPEARANCE.useNativeMacWindowControls,
+ tableDoubleClickAction: sanitizeTableDoubleClickAction(
+ appearance.tableDoubleClickAction,
+ ),
v2SidebarSearchMode: sanitizeV2SidebarSearchMode(
appearance.v2SidebarSearchMode,
),
diff --git a/frontend/src/v2-theme.css b/frontend/src/v2-theme.css
index e460c56..9374a49 100644
--- a/frontend/src/v2-theme.css
+++ b/frontend/src/v2-theme.css
@@ -2608,12 +2608,16 @@ body[data-ui-version="v2"] .gn-v2-explorer-tree-shell .ant-tree {
}
body[data-ui-version="v2"] .gn-v2-explorer-tree-shell .ant-tree-list {
- height: calc(100% - var(--gn-v2-tree-horizontal-scroll-reserve));
+ position: relative;
+ height: 100%;
min-height: 0;
box-sizing: border-box;
+ padding-bottom: var(--gn-v2-tree-horizontal-scroll-reserve);
}
body[data-ui-version="v2"] .gn-v2-explorer-tree-shell .ant-tree-list-holder {
+ box-sizing: border-box;
+ padding-bottom: var(--gn-v2-tree-horizontal-scroll-reserve);
scrollbar-width: thin;
}
@@ -2621,7 +2625,7 @@ body[data-ui-version="v2"] .gn-v2-explorer-tree-shell .ant-tree-list-scrollbar-h
height: 12px !important;
left: 8px !important;
right: 8px !important;
- bottom: calc((var(--gn-v2-tree-horizontal-scroll-reserve) - 12px) * -1) !important;
+ bottom: calc((var(--gn-v2-tree-horizontal-scroll-reserve) - 12px) / 2) !important;
}
body[data-ui-version="v2"] .gn-v2-explorer-tree-shell .ant-tree-list-scrollbar-horizontal .ant-tree-list-scrollbar-thumb {