mirror of
https://github.com/Syngnat/GoNavi.git
synced 2026-06-28 17:31:32 +08:00
🐛 fix(sidebar): 修复左侧树长名称滚动仍截断
- 调整侧栏树节点内容宽度,避免标题层继续被 ellipsis 截断 - 同步 V2 树标题和标签样式,横向滚动后可查看完整名称 - 补充样式回归测试,覆盖节点内容、标题和标签完整宽度
This commit is contained in:
@@ -81,8 +81,8 @@ samp {
|
||||
}
|
||||
|
||||
.sidebar-tree-scroll-shell .ant-tree .ant-tree-node-content-wrapper {
|
||||
width: auto !important;
|
||||
min-width: 0;
|
||||
width: max-content !important;
|
||||
min-width: 100%;
|
||||
display: flex !important;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
@@ -106,7 +106,7 @@ samp {
|
||||
|
||||
.sidebar-tree-scroll-shell .ant-tree .ant-tree-title {
|
||||
flex: 0 0 auto;
|
||||
min-width: 0;
|
||||
min-width: max-content;
|
||||
overflow: visible;
|
||||
text-overflow: clip;
|
||||
}
|
||||
|
||||
@@ -70,6 +70,12 @@ import {
|
||||
} from './V2TableContextMenu';
|
||||
|
||||
const readSourceFile = (relativePath: string) => readFileSync(new URL(relativePath, import.meta.url), 'utf8');
|
||||
const escapeRegExp = (value: string) => value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
||||
const readCssRuleBlock = (css: string, selector: string) => {
|
||||
const match = css.match(new RegExp(`${escapeRegExp(selector)}\\s*\\{(?<body>[^}]*)\\}`, 's'));
|
||||
expect(match, `Missing CSS rule for ${selector}`).not.toBeNull();
|
||||
return match?.groups?.body ?? '';
|
||||
};
|
||||
const readSidebarSource = () => [
|
||||
readSourceFile('./Sidebar.tsx'),
|
||||
readSourceFile('./sidebar/sidebarHelpers.ts'),
|
||||
@@ -1100,14 +1106,30 @@ describe('Sidebar locate toolbar', () => {
|
||||
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);
|
||||
const treeContentWrapperCss = readCssRuleBlock(css, 'body[data-ui-version="v2"] .gn-v2-explorer-tree-shell .ant-tree-node-content-wrapper');
|
||||
expect(treeContentWrapperCss).toContain('min-width: 100%;');
|
||||
expect(treeContentWrapperCss).toContain('width: max-content !important;');
|
||||
expect(treeContentWrapperCss).toContain('display: flex !important;');
|
||||
expect(css).toMatch(/\.gn-v2-tree-title\.is-connection \{[^}]*align-items:\s*center;/s);
|
||||
expect(css).toMatch(/\.gn-v2-explorer-tree-shell \.ant-tree-title \{[^}]*flex: 1 1 auto;[^}]*overflow: visible;/s);
|
||||
expect(css).toMatch(/\.gn-v2-explorer-tree-shell \.ant-tree-title > \.gn-v2-tree-title \{[^}]*overflow: visible;/s);
|
||||
const antTreeTitleCss = readCssRuleBlock(css, 'body[data-ui-version="v2"] .gn-v2-explorer-tree-shell .ant-tree-title');
|
||||
expect(antTreeTitleCss).toContain('min-width: max-content;');
|
||||
expect(antTreeTitleCss).toContain('flex: 0 0 auto;');
|
||||
expect(antTreeTitleCss).toContain('overflow: visible;');
|
||||
const antTreeTitleSpanCss = readCssRuleBlock(css, 'body[data-ui-version="v2"] .gn-v2-explorer-tree-shell .ant-tree-title > span');
|
||||
expect(antTreeTitleSpanCss).toContain('min-width: max-content;');
|
||||
expect(antTreeTitleSpanCss).toContain('overflow: visible;');
|
||||
expect(antTreeTitleSpanCss).toContain('text-overflow: clip;');
|
||||
const v2TreeTitleCss = readCssRuleBlock(css, 'body[data-ui-version="v2"] .gn-v2-explorer-tree-shell .ant-tree-title > .gn-v2-tree-title');
|
||||
expect(v2TreeTitleCss).toContain('width: max-content;');
|
||||
expect(v2TreeTitleCss).toContain('min-width: 100%;');
|
||||
expect(v2TreeTitleCss).toContain('overflow: visible;');
|
||||
expect(css).toMatch(/\.gn-v2-tree-status \{[^}]*width: 14px;[^}]*height: 14px;[^}]*flex: 0 0 14px;[^}]*overflow: visible;/s);
|
||||
expect(css).toMatch(/\.gn-v2-tree-status::before \{[^}]*width: 7px;[^}]*height: 7px;[^}]*border-radius: 50%;/s);
|
||||
expect(css).toMatch(/\.gn-v2-tree-status\.is-success::before \{[^}]*background: #22c55e;[^}]*box-shadow: 0 0 0 4px rgba\(34, 197, 94, 0\.18\);/s);
|
||||
expect(css).toMatch(/\.gn-v2-tree-label \{[^}]*overflow: hidden;[^}]*text-overflow: ellipsis;/s);
|
||||
const treeLabelCss = readCssRuleBlock(css, 'body[data-ui-version="v2"] .gn-v2-tree-label');
|
||||
expect(treeLabelCss).toContain('flex: 0 0 auto;');
|
||||
expect(treeLabelCss).toContain('overflow: visible;');
|
||||
expect(treeLabelCss).toContain('text-overflow: clip;');
|
||||
expect(css).toMatch(/\.gn-v2-tree-title\.is-mono \{[^}]*width: max-content;[^}]*min-width: 100%;[^}]*flex: 0 0 auto;/s);
|
||||
expect(css).toMatch(/\.gn-v2-tree-title\.is-mono \.gn-v2-tree-label \{[^}]*flex: 0 0 auto;[^}]*overflow: visible;[^}]*text-overflow: clip;/s);
|
||||
expect(css).toMatch(/\.gn-v2-tree-folder-icon \{[^}]*width: 22px;[^}]*height: 22px;[^}]*flex: 0 0 22px;/s);
|
||||
|
||||
@@ -8,20 +8,20 @@ const __dirname = path.dirname(__filename);
|
||||
const appCss = readFileSync(path.resolve(__dirname, './App.css'), 'utf8');
|
||||
|
||||
describe('sidebar tree horizontal scroll css', () => {
|
||||
it('keeps the virtual tree width anchored to the sidebar by default', () => {
|
||||
it('lets sidebar tree titles keep their full content width for horizontal scrolling', () => {
|
||||
expect(appCss).toMatch(/\.sidebar-tree-scroll-shell\s+\.ant-tree\s+\.ant-tree-list-holder,\s*\.sidebar-tree-scroll-shell\s+\.ant-tree\s+\.ant-tree-list-holder-inner\s*\{[^}]*min-width:\s*100%;/s);
|
||||
expect(appCss).not.toMatch(/\.sidebar-tree-scroll-shell\s+\.ant-tree\s+\.ant-tree-list-holder,\s*\.sidebar-tree-scroll-shell\s+\.ant-tree\s+\.ant-tree-list-holder-inner\s*\{[^}]*max-content/s);
|
||||
|
||||
expect(appCss).toMatch(/\.sidebar-tree-scroll-shell\s+\.ant-tree\s+\.ant-tree-treenode\s*\{[^}]*width:\s*auto;[^}]*min-width:\s*100%;/s);
|
||||
expect(appCss).not.toMatch(/\.sidebar-tree-scroll-shell\s+\.ant-tree\s+\.ant-tree-treenode\s*\{[^}]*width:\s*max-content/s);
|
||||
|
||||
expect(appCss).toMatch(/\.sidebar-tree-scroll-shell\s+\.ant-tree\s+\.ant-tree-node-content-wrapper\s*\{[^}]*width:\s*auto\s*!important;[^}]*min-width:\s*0;/s);
|
||||
expect(appCss).not.toMatch(/\.sidebar-tree-scroll-shell\s+\.ant-tree\s+\.ant-tree-node-content-wrapper\s*\{[^}]*max-content/s);
|
||||
expect(appCss).toMatch(/\.sidebar-tree-scroll-shell\s+\.ant-tree\s+\.ant-tree-node-content-wrapper\s*\{[^}]*width:\s*max-content\s*!important;[^}]*min-width:\s*100%;/s);
|
||||
expect(appCss).not.toMatch(/\.sidebar-tree-scroll-shell\s+\.ant-tree\s+\.ant-tree-node-content-wrapper\s*\{[^}]*min-width:\s*0;/s);
|
||||
|
||||
expect(appCss).toMatch(/\.sidebar-tree-scroll-shell\s+\.ant-tree\s+\.ant-tree-switcher\s*\{[^}]*width:\s*24px;[^}]*min-width:\s*24px;/s);
|
||||
expect(appCss).toMatch(/\.sidebar-tree-scroll-shell\s+\.ant-tree\s+\.ant-tree-iconEle\s*\{[^}]*width:\s*16px;[^}]*min-width:\s*16px;/s);
|
||||
|
||||
expect(appCss).toMatch(/\.sidebar-tree-scroll-shell\s+\.ant-tree\s+\.ant-tree-title\s*\{[^}]*min-width:\s*0;[^}]*overflow:\s*visible;/s);
|
||||
expect(appCss).not.toMatch(/\.sidebar-tree-scroll-shell\s+\.ant-tree\s+\.ant-tree-title\s*\{[^}]*max-content/s);
|
||||
expect(appCss).toMatch(/\.sidebar-tree-scroll-shell\s+\.ant-tree\s+\.ant-tree-title\s*\{[^}]*min-width:\s*max-content;[^}]*overflow:\s*visible;[^}]*text-overflow:\s*clip;/s);
|
||||
expect(appCss).not.toMatch(/\.sidebar-tree-scroll-shell\s+\.ant-tree\s+\.ant-tree-title\s*\{[^}]*ellipsis/s);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -2661,7 +2661,8 @@ body[data-ui-version="v2"] .gn-v2-explorer-tree-shell .ant-tree-indent-unit {
|
||||
}
|
||||
|
||||
body[data-ui-version="v2"] .gn-v2-explorer-tree-shell .ant-tree-node-content-wrapper {
|
||||
min-width: 0;
|
||||
min-width: 100%;
|
||||
width: max-content !important;
|
||||
min-height: 26px !important;
|
||||
padding: 0 6px !important;
|
||||
display: flex !important;
|
||||
@@ -2720,27 +2721,30 @@ body[data-ui-version="v2"] .gn-v2-explorer-tree-shell .gn-v2-tree-folder-icon .a
|
||||
}
|
||||
|
||||
body[data-ui-version="v2"] .gn-v2-explorer-tree-shell .ant-tree-title {
|
||||
min-width: 0;
|
||||
flex: 1 1 auto;
|
||||
min-width: max-content;
|
||||
flex: 0 0 auto;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
body[data-ui-version="v2"] .gn-v2-explorer-tree-shell .ant-tree-title > span {
|
||||
min-width: 0;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
min-width: max-content;
|
||||
overflow: visible;
|
||||
text-overflow: clip;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
body[data-ui-version="v2"] .gn-v2-explorer-tree-shell .ant-tree-title > .gn-v2-tree-title {
|
||||
width: max-content;
|
||||
min-width: 100%;
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
body[data-ui-version="v2"] .gn-v2-tree-title {
|
||||
width: 100%;
|
||||
min-width: 0;
|
||||
width: max-content;
|
||||
min-width: 100%;
|
||||
flex: 0 0 auto;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 5px;
|
||||
@@ -2824,18 +2828,18 @@ body[data-ui-version="v2"] .gn-v2-tree-status.is-error::before {
|
||||
}
|
||||
|
||||
body[data-ui-version="v2"] .gn-v2-tree-label {
|
||||
min-width: 0;
|
||||
flex: 1 1 auto;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
min-width: max-content;
|
||||
flex: 0 0 auto;
|
||||
overflow: visible;
|
||||
text-overflow: clip;
|
||||
white-space: nowrap;
|
||||
letter-spacing: 0;
|
||||
font-weight: 400 !important;
|
||||
}
|
||||
|
||||
body[data-ui-version="v2"] .gn-v2-tree-connection-copy {
|
||||
min-width: 0;
|
||||
flex: 1 1 auto;
|
||||
min-width: max-content;
|
||||
flex: 0 0 auto;
|
||||
color: var(--gn-fg-1);
|
||||
font-weight: 400 !important;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user