Skip to content

Commit 8dabaaf

Browse files
committed
feat: Enhance tree rendering with improved line connectors and arrow icons for better visual hierarchy
1 parent 63f46ed commit 8dabaaf

File tree

2 files changed

+60
-11
lines changed

2 files changed

+60
-11
lines changed

index.js

Lines changed: 37 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -885,17 +885,41 @@
885885
// ============================================================================
886886
// VIRTUAL RENDERING - Only render visible items
887887
// ============================================================================
888-
const render = (nodes, lv = 0, acc = []) => {
889-
if (acc.length > MAX_RENDER) return acc; // Stop if too many
890-
nodes.forEach(nd => {
888+
// Helper to build tree lines array for each node
889+
function getTreeLines(parents, isLast) {
890+
let lines = '';
891+
for (let i = 0; i < parents.length; ++i) {
892+
lines += `<span class="tree-vline" style="visibility:${parents[i] ? 'visible' : 'hidden'}"></span>`;
893+
}
894+
// For the current node, add a connector (├ or └)
895+
if (parents.length > 0) {
896+
lines += `<span class="tree-vline tree-branch" style="height:22px;${isLast ? 'border-left:2px solid transparent;' : ''}"></span>`;
897+
}
898+
return lines;
899+
}
900+
901+
const render = (nodes, lv = 0, acc = [], parents = []) => {
902+
if (acc.length > MAX_RENDER) return acc;
903+
nodes.forEach((nd, idx) => {
891904
const ic = ico(nd.n, nd.t === 'd');
892905
const has = nd.t === 'd' && nd.kids.size > 0;
893906
const sz = nd.f ? bytes(nd.f.size) : '';
907+
const isLast = idx === nodes.length - 1;
908+
// Tree lines
909+
const lines = getTreeLines(parents, isLast);
910+
// Arrow SVGs
911+
let arrow = '';
912+
if (has) {
913+
arrow = `<img class="tree-arrow" src="public/arrowRight.svg" data-arrow="right" style="display:inline;" />`;
914+
} else {
915+
arrow = `<span class="tree-arrow-placeholder"></span>`;
916+
}
894917
acc.push({
895-
html: `<div class="tree-item ${nd.ig ? 'ignored' : ''}" data-path="${nd.full}">
918+
html: `<div class="tree-item${nd.ig ? ' ignored' : ''}${has ? ' folder' : ''}" data-path="${nd.full}">
896919
<div class="tree-item-content" data-level="${lv}">
920+
<span class="tree-lines">${lines}</span>
897921
<button class="expand-btn" style="visibility:${has ? 'visible' : 'hidden'}">
898-
<span class="material-symbols-outlined">chevron_right</span>
922+
${arrow}
899923
</button>
900924
<div class="file-icon ${ic.cls}">
901925
<img src="${ic.url}" alt="${nd.n}" class="vscode-icon" onerror="this.style.display='none'" />
@@ -906,13 +930,14 @@
906930
</label>
907931
${sz ? `<span class="file-size">${sz}</span>` : ''}
908932
</div>
909-
${has ? `<div class="tree-children">${renderSub(Array.from(nd.kids.values()), lv + 1)}</div>` : ''}
933+
${has ? `<div class="tree-children">${renderSub(Array.from(nd.kids.values()), lv + 1, parents.concat(!isLast))}</div>` : ''}
910934
</div>`
911935
});
912936
});
913937
return acc;
914938
};
915-
const renderSub = (nodes, lv) => render(nodes, lv, []).map(x => x.html).join('');
939+
// Pass parents array for lines
940+
const renderSub = (nodes, lv, parents) => render(nodes, lv, [], parents).map(x => x.html).join('');
916941
// ============================================================================
917942
// FILE LOADING - ASYNC CHUNKS (ENHANCED FILTERING & UI UPDATE)
918943
// ============================================================================
@@ -1380,10 +1405,14 @@
13801405
if (btn) {
13811406
const item = btn.closest('.tree-item');
13821407
const kids = item.querySelector('.tree-children');
1408+
const arrowImg = btn.querySelector('.tree-arrow');
13831409
if (kids) {
13841410
const open = kids.classList.toggle('open');
13851411
btn.classList.toggle('expanded', open);
1386-
btn.querySelector('.material-symbols-outlined').textContent = open ? 'expand_more' : 'chevron_right';
1412+
if (arrowImg) {
1413+
arrowImg.src = open ? 'public/arrowDown.svg' : 'public/arrowRight.svg';
1414+
arrowImg.setAttribute('data-arrow', open ? 'down' : 'right');
1415+
}
13871416
}
13881417
return;
13891418
}

style.css

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,13 @@
2525
margin-bottom: 2px;
2626
}
2727
/* Tree lines and arrows */
28+
/* Tree lines and arrows (VS Code style) */
2829
.tree-lines {
2930
display: inline-block;
3031
min-width: 0.7em;
3132
vertical-align: middle;
33+
user-select: none;
34+
letter-spacing: -0.1em;
3235
}
3336
.tree-vline {
3437
display: inline-block;
@@ -41,15 +44,32 @@
4144
position: relative;
4245
top: 2px;
4346
}
47+
.tree-branch {
48+
width: 16px;
49+
height: 22px;
50+
background: none;
51+
border-left: 2px solid #444;
52+
border-bottom: 2px solid #444;
53+
border-radius: 0 0 0 2px;
54+
margin-right: 2px;
55+
margin-left: -2px;
56+
position: relative;
57+
top: 2px;
58+
left: -2px;
59+
}
4460
.tree-arrow {
4561
width: 14px;
4662
height: 14px;
4763
vertical-align: middle;
4864
margin-right: 2px;
49-
transition: transform 0.15s;
65+
transition: none;
66+
display: inline-block;
5067
}
51-
.tree-item.open > .tree-item-content > .expand-btn .tree-arrow {
52-
transform: rotate(90deg);
68+
.tree-arrow-placeholder {
69+
display: inline-block;
70+
width: 14px;
71+
height: 14px;
72+
margin-right: 2px;
5373
}
5474
/* Tree lines and arrows */
5575
.tree-lines {

0 commit comments

Comments
 (0)