feat(folder-browser): improve expand/collapse interaction and row styling

Make expandable folder rows clearly distinguishable and allow clicking the
left-side toggle zone to expand/collapse folders instead of selecting them.

- Add is-expandable class and data-state-key to expandable rows
- Extract toggleFolderBrowserState helper for reuse
- Extract isFolderBrowserToggleZoneClick to detect toggle-zone clicks
- Adjust toggle button width/positioning via CSS for expandable rows
- Apply box-sizing: border-box to folder browser toggle
This commit is contained in:
Dariusz L
2026-06-23 04:48:05 +02:00
parent baa8849fa4
commit f94abe1489
2 changed files with 49 additions and 11 deletions
+8
View File
@@ -5785,6 +5785,7 @@
box-shadow: inset 0 0 0 1px rgba(114,211,138,0.32);
}
.mr-folder-browser-toggle {
box-sizing: border-box;
width: 18px;
height: 18px;
min-width: 18px;
@@ -5798,6 +5799,13 @@
justify-content: center;
cursor: pointer;
}
.mr-folder-browser-row.is-expandable .mr-folder-browser-toggle {
width: 29px;
min-width: 29px;
margin-left: -7px;
margin-right: -4px;
padding-left: 7px;
}
.mr-folder-browser-toggle:hover {
background: rgba(255,255,255,0.06);
color: var(--mr-text);
+41 -11
View File
@@ -1772,10 +1772,18 @@ export const downloadTargetMethods = {
const children = hasChildren
? `<div class="mr-folder-browser-children ${shouldExpand ? 'is-expanded' : ''}">${renderFolderTreeNodes(node.children, rootGroup, expandedSet, filter, selectedValue, selectedBaseDirectory)}</div>`
: '';
const rowClass = [
'mr-folder-browser-row',
isSelected ? 'is-selected' : '',
hasChildren ? 'is-expandable' : ''
].filter(Boolean).join(' ');
const rowStateAttribute = hasChildren
? ` data-state-key="${encodeURIComponent(stateKey)}"`
: '';
return `
<div class="mr-folder-browser-node">
<div class="mr-folder-browser-row ${isSelected ? 'is-selected' : ''}" data-browser-action="select" data-value="${encodeURIComponent(nodeValue)}" data-base-directory="${encodeURIComponent(nodeBaseDirectory)}">
<div class="${rowClass}" data-browser-action="select" data-value="${encodeURIComponent(nodeValue)}" data-base-directory="${encodeURIComponent(nodeBaseDirectory)}"${rowStateAttribute}>
${toggle}
<span class="mr-folder-browser-folder-icon">${getSvgIcon('folderOpen', 'currentColor', 'mr-folder-browser-svg')}</span>
<span class="mr-folder-browser-name">${this.escapeHtml(node.name)}</span>
@@ -1890,20 +1898,38 @@ export const downloadTargetMethods = {
requestAnimationFrame(restoreScrollPosition);
}
const toggleFolderBrowserState = (encodedStateKey) => {
const stateKey = decodeURIComponent(encodedStateKey || '');
if (!stateKey) return;
if (expandedSet.has(stateKey)) {
expandedSet.delete(stateKey);
} else {
expandedSet.add(stateKey);
}
renderDownloadFolderBrowser(targetEl, folders, filterText, onSelect, {
preserveScroll: true
});
};
const isFolderBrowserToggleZoneClick = (event, row) => {
if (!row?.dataset?.stateKey) return false;
const rowRect = row.getBoundingClientRect();
const toggleEl = row.querySelector('.mr-folder-browser-toggle:not(.mr-folder-browser-toggle-empty)');
const folderIconEl = row.querySelector('.mr-folder-browser-folder-icon');
const toggleRect = toggleEl?.getBoundingClientRect();
const iconRect = folderIconEl?.getBoundingClientRect();
const toggleZoneRight = Math.max(
toggleRect?.right || rowRect.left,
iconRect?.left || rowRect.left
);
return event.clientX >= rowRect.left && event.clientX <= toggleZoneRight;
};
targetEl.querySelectorAll('[data-browser-action="toggle"]').forEach(button => {
button.addEventListener('mousedown', (event) => {
event.preventDefault();
event.stopPropagation();
const stateKey = decodeURIComponent(button.dataset.stateKey || '');
if (!stateKey) return;
if (expandedSet.has(stateKey)) {
expandedSet.delete(stateKey);
} else {
expandedSet.add(stateKey);
}
renderDownloadFolderBrowser(targetEl, folders, filterText, onSelect, {
preserveScroll: true
});
toggleFolderBrowserState(button.dataset.stateKey || '');
});
});
@@ -1911,6 +1937,10 @@ export const downloadTargetMethods = {
row.addEventListener('mousedown', (event) => {
event.preventDefault();
event.stopPropagation();
if (isFolderBrowserToggleZoneClick(event, row)) {
toggleFolderBrowserState(row.dataset.stateKey || '');
return;
}
const value = decodeURIComponent(row.dataset.value || '');
const baseDirectory = decodeURIComponent(row.dataset.baseDirectory || '');
onSelect(value, '', baseDirectory);