🐛 fix(sidebar): 修复 v2 侧栏横向滚动条位置

This commit is contained in:
Syngnat
2026-06-02 18:06:31 +08:00
parent c315ea9c96
commit 3eb9fd0acb
3 changed files with 41 additions and 6 deletions

View File

@@ -659,12 +659,25 @@ describe('Sidebar locate toolbar', () => {
expect(source).toContain("overflow: 'hidden'");
expect(source).not.toContain("overflowX: isV2Ui ? 'auto' : 'hidden'");
expect(source).toContain('scrollWidth={isV2Ui ? v2TreeHorizontalScrollWidth : undefined}');
expect(css).toMatch(/\.gn-v2-explorer-tree-shell \{[^}]*overflow: hidden !important;/s);
expect(css).toMatch(/\.gn-v2-explorer-tree-shell \.ant-tree \{[^}]*width: 100%;[^}]*min-width: 0;/s);
expect(source).toContain('const V2_TREE_HORIZONTAL_SCROLL_BOTTOM_RESERVE = 32;');
expect(source).toContain('const effectiveTreeHeight = isV2Ui && v2TreeHorizontalScrollWidth');
expect(source).toContain('treeHeight - V2_TREE_HORIZONTAL_SCROLL_BOTTOM_RESERVE');
expect(source).toContain('height={effectiveTreeHeight}');
expect(source).toContain('treeData={isV2Ui ? v2VisibleTreeData : displayTreeData}');
expect(source).not.toContain('__v2-tree-horizontal-scroll-spacer__');
expect(source).not.toContain('v2TreeDataWithScrollSpacer');
expect(css).toMatch(/\.gn-v2-explorer-tree-shell \{[^}]*--gn-v2-tree-horizontal-scroll-reserve: 32px;[^}]*overflow: hidden !important;/s);
expect(css).toMatch(/\.gn-v2-explorer-tree-shell \.sidebar-tree-scroll-content \{[^}]*display: flex;[^}]*height: 100%;[^}]*padding: 4px 0 0;/s);
expect(css).toMatch(/\.gn-v2-explorer-tree-shell \.ant-tree \{[^}]*flex: 1 1 auto;[^}]*width: 100%;[^}]*min-width: 0;[^}]*height: 100%;/s);
expect(css).toMatch(/\.gn-v2-explorer-tree-shell \.ant-tree-list \{[^}]*height: calc\(100% - var\(--gn-v2-tree-horizontal-scroll-reserve\)\);[^}]*min-height: 0;[^}]*box-sizing: border-box;/s);
expect(css).not.toMatch(/\.gn-v2-explorer-tree-shell \.ant-tree-list \{[^}]*height: 100%;/s);
expect(css).toMatch(/\.gn-v2-explorer-tree-shell \.ant-tree-list-holder-inner \{[^}]*width: 100%;[^}]*min-width: 100%;/s);
expect(css).not.toMatch(/\.gn-v2-explorer-tree-shell \.ant-tree-list-holder-inner \{[^}]*width: max-content;/s);
expect(css).not.toMatch(/\.gn-v2-explorer-tree-shell \.ant-tree-list \{[^}]*position: static !important;/s);
expect(css).not.toMatch(/\.gn-v2-explorer-tree-shell \.ant-tree-list-holder \{[^}]*calc\(100% - var\(--gn-v2-tree-horizontal-scroll-reserve\)\)/s);
expect(css).not.toMatch(/\.gn-v2-explorer-tree-shell \.ant-tree-list-holder \{[^}]*overflow-x: auto !important;/s);
expect(css).toMatch(/\.gn-v2-explorer-tree-shell \.ant-tree-list-scrollbar-horizontal \{[^}]*height: 12px !important;/s);
expect(css).toMatch(/\.gn-v2-explorer-tree-shell \.ant-tree-list-scrollbar-horizontal \{[^}]*height: 12px !important;[^}]*bottom: calc\(\(var\(--gn-v2-tree-horizontal-scroll-reserve\) - 12px\) \* -1\) !important;/s);
expect(css).not.toContain('.gn-v2-tree-horizontal-scroll-spacer');
expect(css).toMatch(/\.gn-v2-explorer-tree-shell \.ant-tree-list-scrollbar-horizontal \.ant-tree-list-scrollbar-thumb \{[^}]*height: 8px !important;/s);
expect(css).toMatch(/\.gn-v2-explorer-tree-shell \.ant-tree-node-content-wrapper \{[^}]*display: flex !important;/s);
expect(css).toMatch(/\.gn-v2-tree-title\.is-connection \{[^}]*align-items:\s*center;/s);

View File

@@ -427,6 +427,7 @@ const V2_TREE_HORIZONTAL_SCROLL_BASE_WIDTH = 88;
const V2_TREE_HORIZONTAL_SCROLL_INDENT_WIDTH = 24;
const V2_TREE_HORIZONTAL_SCROLL_AVG_CHAR_WIDTH = 8;
const V2_TREE_HORIZONTAL_SCROLL_VIEWPORT_BUFFER = 48;
const V2_TREE_HORIZONTAL_SCROLL_BOTTOM_RESERVE = 32;
export const estimateV2TreeHorizontalScrollWidth = (
nodes: TreeNode[],
@@ -6159,6 +6160,9 @@ const Sidebar: React.FC<{
() => estimateV2TreeHorizontalScrollWidth(v2VisibleTreeData, treeViewportWidth),
[treeViewportWidth, v2VisibleTreeData],
);
const effectiveTreeHeight = isV2Ui && v2TreeHorizontalScrollWidth
? Math.max(1, treeHeight - V2_TREE_HORIZONTAL_SCROLL_BOTTOM_RESERVE)
: treeHeight;
const v2TreeMetrics = useMemo(() => {
const databaseTableCounts = new Map<React.Key, number>();
const objectGroupCounts = new Map<React.Key, number>();
@@ -8850,7 +8854,7 @@ const Sidebar: React.FC<{
autoExpandParent={autoExpandParent}
selectedKeys={selectedKeys}
blockNode
height={treeHeight}
height={effectiveTreeHeight}
scrollWidth={isV2Ui ? v2TreeHorizontalScrollWidth : undefined}
onRightClick={onRightClick}
/>

View File

@@ -2222,6 +2222,7 @@ body[data-ui-version="v2"] .gn-v2-explorer-toolbar {
}
body[data-ui-version="v2"] .gn-v2-explorer-tree-shell {
--gn-v2-tree-horizontal-scroll-reserve: 32px;
margin: 0;
border: 0;
border-radius: 0;
@@ -2230,23 +2231,39 @@ body[data-ui-version="v2"] .gn-v2-explorer-tree-shell {
}
body[data-ui-version="v2"] .gn-v2-explorer-tree-shell .sidebar-tree-scroll-content {
padding: 4px 0 12px;
display: flex;
flex-direction: column;
min-height: 0;
height: 100%;
box-sizing: border-box;
padding: 4px 0 0;
}
body[data-ui-version="v2"] .gn-v2-explorer-tree-shell .ant-tree {
flex: 1 1 auto;
width: 100%;
min-width: 0;
min-height: 0;
height: 100%;
font-size: var(--gn-sidebar-tree-font-size, var(--gn-font-size-sm, 12px));
line-height: 1.2;
}
body[data-ui-version="v2"] .gn-v2-explorer-tree-shell .ant-tree-list {
height: calc(100% - var(--gn-v2-tree-horizontal-scroll-reserve));
min-height: 0;
box-sizing: border-box;
}
body[data-ui-version="v2"] .gn-v2-explorer-tree-shell .ant-tree-list-holder {
scrollbar-width: thin;
}
body[data-ui-version="v2"] .gn-v2-explorer-tree-shell .ant-tree-list-scrollbar-horizontal {
height: 12px !important;
bottom: 1px !important;
left: 8px !important;
right: 8px !important;
bottom: calc((var(--gn-v2-tree-horizontal-scroll-reserve) - 12px) * -1) !important;
}
body[data-ui-version="v2"] .gn-v2-explorer-tree-shell .ant-tree-list-scrollbar-horizontal .ant-tree-list-scrollbar-thumb {
@@ -2263,6 +2280,7 @@ body[data-ui-version="v2"] .gn-v2-explorer-tree-shell .ant-tree-list-scrollbar-h
body[data-ui-version="v2"] .gn-v2-explorer-tree-shell .ant-tree-list-holder-inner {
width: 100%;
min-width: 100%;
box-sizing: border-box;
}
body[data-ui-version="v2"] .gn-v2-explorer-tree-shell .ant-tree-treenode {