2х рядный режим для дерева

This commit is contained in:
Илья Братских 2026-06-28 15:07:32 +03:00 committed by KBAHTNET
parent 6aa5daf9ea
commit 15c6215eef
3 changed files with 88 additions and 5 deletions

View File

@ -132,11 +132,20 @@
<label class="toggle-row"> <label class="toggle-row">
<span> <span>
<strong>Показывать теги дерева</strong> <strong>Показывать теги дерева</strong>
<small>Поисковые теги рядом с элементом</small> <small>Теги рядом с элементом, без 2 колонок</small>
</span> </span>
<input type="checkbox" data-show-tree-tags /> <input type="checkbox" data-show-tree-tags />
</label> </label>
<!-- Элементы внутри папок дерева отображаются в две колонки без тегов. -->
<label class="toggle-row">
<span>
<strong>2 колонки в дереве</strong>
<small>Компактный вид элементов папок</small>
</span>
<input type="checkbox" data-tree-two-column />
</label>
<!-- Управляет тем, раскрывает ли поиск только ветки с совпадениями. --> <!-- Управляет тем, раскрывает ли поиск только ветки с совпадениями. -->
<label class="toggle-row"> <label class="toggle-row">
<span> <span>

View File

@ -171,6 +171,7 @@ const defaultPreferences = {
customAccentAngle: 135, customAccentAngle: 135,
showNumbers: false, showNumbers: false,
showTreeTags: true, showTreeTags: true,
treeTwoColumn: false,
autoCollapseSearch: true, autoCollapseSearch: true,
sidebarWidth: 390, sidebarWidth: 390,
}; };
@ -206,6 +207,7 @@ const customAccentAngleValue = document.querySelector("[data-custom-accent-angle
const customAccentPreview = document.querySelector("[data-custom-accent-preview]"); const customAccentPreview = document.querySelector("[data-custom-accent-preview]");
const showNumbersInput = document.querySelector("[data-show-numbers]"); const showNumbersInput = document.querySelector("[data-show-numbers]");
const showTreeTagsInput = document.querySelector("[data-show-tree-tags]"); const showTreeTagsInput = document.querySelector("[data-show-tree-tags]");
const treeTwoColumnInput = document.querySelector("[data-tree-two-column]");
const autoCollapseSearchInput = document.querySelector("[data-auto-collapse-search]"); const autoCollapseSearchInput = document.querySelector("[data-auto-collapse-search]");
const emptyTemplate = document.querySelector("#empty-template"); const emptyTemplate = document.querySelector("#empty-template");
@ -326,8 +328,26 @@ showNumbersInput.addEventListener("change", () => {
}); });
// Показывает/скрывает поисковые теги в файловом дереве. // Показывает/скрывает поисковые теги в файловом дереве.
// Взаимоисключимо с двухколоночным режимом элементов папок.
showTreeTagsInput.addEventListener("change", () => { showTreeTagsInput.addEventListener("change", () => {
preferences.showTreeTags = showTreeTagsInput.checked; preferences.showTreeTags = showTreeTagsInput.checked;
if (preferences.showTreeTags) {
preferences.treeTwoColumn = false;
}
applyPreferences(preferences);
savePreferences(preferences);
});
// Компактный двухколоночный режим элементов внутри папок дерева.
// Взаимоисключимо с отображением тегов.
treeTwoColumnInput.addEventListener("change", () => {
preferences.treeTwoColumn = treeTwoColumnInput.checked;
if (preferences.treeTwoColumn) {
preferences.showTreeTags = false;
if (preferences.sidebarWidth < 480) {
preferences.sidebarWidth = 480;
}
}
applyPreferences(preferences); applyPreferences(preferences);
savePreferences(preferences); savePreferences(preferences);
}); });
@ -349,7 +369,9 @@ sidebarResizer.addEventListener("pointerdown", (event) => {
const handlePointerMove = (moveEvent) => { const handlePointerMove = (moveEvent) => {
const layoutLeft = document.querySelector(".app-layout").getBoundingClientRect().left; const layoutLeft = document.querySelector(".app-layout").getBoundingClientRect().left;
preferences.sidebarWidth = Math.round(clamp(moveEvent.clientX - layoutLeft, 260, 560)); preferences.sidebarWidth = Math.round(
clamp(moveEvent.clientX - layoutLeft, 260, getSidebarMaxWidth(preferences)),
);
applyPreferences(preferences); applyPreferences(preferences);
}; };
@ -754,19 +776,39 @@ function applyPreferences(nextPreferences) {
360, 360,
); );
if (nextPreferences.treeTwoColumn) {
nextPreferences.showTreeTags = false;
} else if (nextPreferences.showTreeTags) {
nextPreferences.treeTwoColumn = false;
}
document.documentElement.dataset.theme = nextPreferences.theme; document.documentElement.dataset.theme = nextPreferences.theme;
document.documentElement.dataset.accent = nextPreferences.accent; document.documentElement.dataset.accent = nextPreferences.accent;
applyAccentVariables(nextPreferences); applyAccentVariables(nextPreferences);
document.documentElement.style.setProperty( document.documentElement.style.setProperty(
"--sidebar-width", "--sidebar-width",
`${clamp(Number(nextPreferences.sidebarWidth) || defaultPreferences.sidebarWidth, 260, 560)}px`, `${clamp(
Number(nextPreferences.sidebarWidth) || defaultPreferences.sidebarWidth,
260,
getSidebarMaxWidth(nextPreferences),
)}px`,
);
document.documentElement.style.setProperty(
"--shell-max-width",
nextPreferences.treeTwoColumn ? "1920px" : "1560px",
);
document.documentElement.style.setProperty(
"--sidebar-max-width",
`${getSidebarMaxWidth(nextPreferences)}px`,
); );
catalog.classList.remove("cards-view", "list-view", "compact-cards-view", "compact-list-view"); catalog.classList.remove("cards-view", "list-view", "compact-cards-view", "compact-list-view");
catalog.classList.add(`${nextPreferences.view}-view`); catalog.classList.add(`${nextPreferences.view}-view`);
document.documentElement.dataset.showNumbers = String(Boolean(nextPreferences.showNumbers)); document.documentElement.dataset.showNumbers = String(Boolean(nextPreferences.showNumbers));
document.documentElement.dataset.showTreeTags = String(Boolean(nextPreferences.showTreeTags)); document.documentElement.dataset.showTreeTags = String(Boolean(nextPreferences.showTreeTags));
document.documentElement.dataset.treeTwoColumn = String(Boolean(nextPreferences.treeTwoColumn));
showNumbersInput.checked = Boolean(nextPreferences.showNumbers); showNumbersInput.checked = Boolean(nextPreferences.showNumbers);
showTreeTagsInput.checked = Boolean(nextPreferences.showTreeTags); showTreeTagsInput.checked = Boolean(nextPreferences.showTreeTags);
treeTwoColumnInput.checked = Boolean(nextPreferences.treeTwoColumn);
autoCollapseSearchInput.checked = Boolean(nextPreferences.autoCollapseSearch); autoCollapseSearchInput.checked = Boolean(nextPreferences.autoCollapseSearch);
customAccentFromInput.value = nextPreferences.customAccentFrom; customAccentFromInput.value = nextPreferences.customAccentFrom;
customAccentToInput.value = nextPreferences.customAccentTo; customAccentToInput.value = nextPreferences.customAccentTo;
@ -930,6 +972,11 @@ function clamp(value, min, max) {
return Math.min(Math.max(value, min), max); return Math.min(Math.max(value, min), max);
} }
// Максимальная ширина sidebar зависит от режима дерева.
function getSidebarMaxWidth(nextPreferences) {
return nextPreferences.treeTwoColumn ? 760 : 560;
}
// ============================================================================ // ============================================================================
// localStorage helpers // localStorage helpers
// ============================================================================ // ============================================================================

View File

@ -24,6 +24,8 @@
--card-x: 50%; --card-x: 50%;
--card-y: 50%; --card-y: 50%;
--sidebar-width: 390px; --sidebar-width: 390px;
--shell-max-width: 1560px;
--sidebar-max-width: 560px;
} }
/* Светлая тема переопределяет только токены, структура стилей остается общей. */ /* Светлая тема переопределяет только токены, структура стилей остается общей. */
@ -128,7 +130,7 @@ a {
========================================================================== */ ========================================================================== */
.shell { .shell {
width: min(1560px, calc(100% - 28px)); width: min(var(--shell-max-width), calc(100% - 28px));
margin: 0 auto; margin: 0 auto;
padding: 20px 0; padding: 20px 0;
} }
@ -269,6 +271,27 @@ html[data-show-tree-tags="false"] .tree-node small {
display: none; display: none;
} }
/* Двухколоночный режим элементов внутри папок дерева. */
html[data-tree-two-column="true"] {
--shell-max-width: 1920px;
--sidebar-max-width: 760px;
}
html[data-tree-two-column="true"] .tree-items {
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: 2px 8px;
}
html[data-tree-two-column="true"] .tree-node.tree-file {
grid-template-columns: 16px minmax(0, 1fr);
min-height: 24px;
font-size: 0.8rem;
}
html[data-tree-two-column="true"] .tree-node.tree-file small {
display: none;
}
/* Подсветка совпадений поиска в дереве и в карточках. */ /* Подсветка совпадений поиска в дереве и в карточках. */
.search-mark { .search-mark {
border-radius: 4px; border-radius: 4px;
@ -1357,7 +1380,7 @@ html[data-theme="light"] .accent-swatch-custom {
@media (max-width: 720px) { @media (max-width: 720px) {
.shell { .shell {
width: min(100% - 22px, 1320px); width: min(var(--shell-max-width), calc(100% - 22px));
padding: 14px 0; padding: 14px 0;
} }
@ -1385,6 +1408,10 @@ html[data-theme="light"] .accent-swatch-custom {
overflow: auto; overflow: auto;
} }
html[data-tree-two-column="true"] .tree-items {
grid-template-columns: 1fr;
}
.control-panel, .control-panel,
.catalog-section, .catalog-section,
.empty-state { .empty-state {