Add resizable compact folder sidebar

This commit is contained in:
Mikei386
2026-07-14 18:25:47 +02:00
parent e4440ddef0
commit e3b95abca6
5 changed files with 75 additions and 8 deletions
+37 -1
View File
@@ -119,6 +119,7 @@ function openExplorer(initialPath = state.config?.roots?.[0]?.path) {
selectionAnchorPath: null,
view: 'icons',
treeVisible: true,
treeWidth: 220,
treeExpanded: [],
treeChildren: {},
treeLoading: [],
@@ -317,8 +318,9 @@ function renderExplorer(body, win) {
<button class="icon ${data.view === 'icons' ? 'active' : ''}" data-action="view-icons" title="Symbolansicht" aria-label="Symbolansicht">${iconSvg('grid')}</button>
</div>
</div>
<div class="explorer-layout ${data.treeVisible ? 'with-tree' : ''}">
<div class="explorer-layout ${data.treeVisible ? 'with-tree' : ''}" style="--tree-width:${Number(data.treeWidth) || 220}px">
${data.treeVisible ? renderFolderTree(win) : ''}
${data.treeVisible ? '<div class="tree-resizer" data-action="resize-tree" role="separator" aria-label="Breite der Ordnerstruktur ändern" aria-orientation="vertical"></div>' : ''}
<div class="explorer-content">
<div class="drop-zone ${data.dragOver ? 'drag-over' : ''}">
${data.error ? `<p class="muted explorer-message">${escapeHtml(data.error)}</p>` : ''}
@@ -342,6 +344,7 @@ function renderExplorer(body, win) {
body.querySelector('[data-action="upload-folder"]').addEventListener('click', () => body.querySelector('[data-upload="folder"]').click());
body.querySelector('[data-action="delete-selected"]').addEventListener('click', () => deleteEntries(win));
bindFolderTree(body, win);
body.querySelector('[data-action="resize-tree"]')?.addEventListener('pointerdown', (event) => startTreeResize(event, win, body));
for (const inputEl of body.querySelectorAll('.upload-input')) {
inputEl.addEventListener('change', async () => {
try {
@@ -491,6 +494,39 @@ function bindFolderTree(body, win) {
}
}
function startTreeResize(event, win, body) {
if (event.button !== 0) return;
event.preventDefault();
event.stopPropagation();
const handle = event.currentTarget;
const layout = body.querySelector('.explorer-layout');
const startX = event.clientX;
const startWidth = Number(win.data.treeWidth) || body.querySelector('.folder-tree')?.getBoundingClientRect().width || 220;
const pointerId = event.pointerId;
handle.classList.add('active');
try {
handle.setPointerCapture(pointerId);
} catch {}
const move = (moveEvent) => {
const maxWidth = Math.max(180, Math.min(480, body.clientWidth - 240));
win.data.treeWidth = Math.round(clamp(startWidth + moveEvent.clientX - startX, 150, maxWidth));
layout?.style.setProperty('--tree-width', `${win.data.treeWidth}px`);
};
const up = () => {
handle.classList.remove('active');
handle.removeEventListener('pointermove', move);
handle.removeEventListener('pointerup', up);
handle.removeEventListener('pointercancel', up);
try {
handle.releasePointerCapture(pointerId);
} catch {}
};
handle.addEventListener('pointermove', move);
handle.addEventListener('pointerup', up);
handle.addEventListener('pointercancel', up);
}
function renderFileEntries(entries, view, selectedPaths = new Set()) {
if (!entries.length) {
return '<p class="muted">Dieser Ordner ist leer. Dateien können hier abgelegt werden.</p>';
+35 -4
View File
@@ -313,7 +313,7 @@
}
.u-nav .explorer-layout.with-tree {
grid-template-columns: clamp(180px, 25%, 250px) minmax(0, 1fr);
grid-template-columns: clamp(150px, var(--tree-width, 220px), 55%) 6px minmax(0, 1fr);
}
.u-nav .explorer-content {
@@ -331,6 +331,32 @@
min-width: 0;
}
.u-nav .tree-resizer {
background: var(--surface);
border-left: 1px solid transparent;
border-right: 1px solid var(--line);
cursor: ew-resize;
min-height: 0;
position: relative;
touch-action: none;
width: 6px;
z-index: 3;
}
.u-nav .tree-resizer::after {
background: transparent;
border-radius: 999px;
content: "";
inset: 8px 1px;
position: absolute;
transition: background-color 140ms ease;
}
.u-nav .tree-resizer:hover::after,
.u-nav .tree-resizer.active::after {
background: var(--accent);
}
.u-nav .tree-heading {
align-items: center;
border-bottom: 1px solid var(--line);
@@ -398,12 +424,17 @@
color: inherit;
display: flex;
flex: 1;
gap: 7px;
justify-content: flex-start;
gap: 5px !important;
justify-content: flex-start !important;
min-width: 0;
overflow: hidden;
padding: 0 5px 0 2px;
text-align: left;
text-align: left !important;
}
.u-nav .tree-label > * {
margin-left: 0 !important;
margin-right: 0 !important;
}
.u-nav .tree-label:hover,