Folder Sidebar

This commit is contained in:
2026-06-16 15:03:18 +02:00
parent 7fe0013a5c
commit 9ed6475775
6 changed files with 330 additions and 16 deletions
+62 -6
View File
@@ -41,6 +41,9 @@
sidebar/TOC top offsets and anchor scroll-padding. Hardcoded (the
desktop header is a single-row grid); revisit if the header wraps. */
--header-h: 3.25rem;
/* Width of the persistent left folder-tree rail (desktop). */
--tree-width: 15rem;
}
/* Anchor / TOC jumps land below the sticky header instead of behind it.
@@ -89,9 +92,9 @@ hr { border: none; border-top: var(--border-dashed); margin: var(--space-4) 0; }
will silently break. */
.page-wrap {
display: grid;
grid-template-columns: minmax(0, 1fr) 14rem;
grid-template-columns: var(--tree-width) minmax(0, 1fr) 14rem;
gap: var(--space-5);
max-width: 1280px;
max-width: 1440px;
margin: 0 auto;
padding: 0 var(--space-4);
width: 100%;
@@ -602,17 +605,44 @@ aside.sidebar:empty { display: none; }
}
.tree-row.is-disabled { color: var(--text-muted); cursor: default; }
.tree-row.is-disabled:hover { background: none; }
.tree-chevron, .tree-marker { text-align: center; flex-shrink: 0; }
.tree-chevron { text-align: center; flex-shrink: 0; }
.tree-chevron { width: 1.25rem; color: var(--secondary); }
.tree-chevron.is-leaf { visibility: hidden; }
.tree-marker { width: var(--space-4); color: var(--text-muted); }
.tree-name { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tree-children { padding-left: var(--space-5); }
.tree-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tree-children { padding-left: var(--space-2); }
.tree-selected-path {
font-size: var(--font-sm);
padding: var(--space-1) 0;
word-break: break-all;
}
/* Current-page row in the navigation rail. Mirrors .tree-row.is-selected so the
two tree surfaces stay visually consistent. */
.tree-row.is-active {
background: var(--bg-panel-hover);
border-left: 3px solid var(--primary);
padding-left: calc(var(--space-2) - 3px);
}
.tree-row.is-active > .tree-name { color: var(--primary-hover); }
/* === Tree sidebar (persistent left navigation rail) ===
Reuses the .tree-row / .tree-children / .tree-name / .tree-chevron modules.
Desktop: a sticky, scrollable rail parked below the header (mirrors .sidebar
offsets). Mobile: an overlay drawer toggled by .fab-tree (see responsive). */
.tree-sidebar {
position: sticky;
top: calc(var(--header-h) + var(--space-2));
align-self: start;
max-height: calc(100vh - var(--header-h) - var(--space-4));
overflow-y: auto;
padding-top: 1rem;
padding-right: var(--space-2);
border-right: var(--border-dashed);
font-size: var(--font-sm);
/* Rows are click targets (navigate / toggle), not prose — suppress the
text-selection highlight that double/drag clicks would otherwise leave. */
user-select: none;
}
aside.tree-sidebar:empty { display: none; }
/* === Movie info box === */
.movie-info { margin: var(--space-3) 0; }
@@ -721,6 +751,32 @@ aside.sidebar:empty { display: none; }
}
.sidebar.is-open { display: flex; }
button.fab { display: inline-flex; }
/* Tree rail becomes a left-anchored overlay drawer toggled by .fab-tree.
Off-grid (position: fixed) so it never steals horizontal space from
<main> on narrow viewports. */
.tree-sidebar {
position: fixed;
top: auto;
bottom: 5rem;
left: var(--space-4);
right: auto;
width: calc(100% - 2rem);
max-width: 20rem;
max-height: calc(100vh - 8rem);
padding: var(--space-2);
border: var(--border);
background: var(--bg);
display: none;
z-index: 60;
}
.tree-sidebar.is-open { display: block; }
/* Smaller FAB stacked just above the menu FAB (3rem tall at --space-4). */
.fab-tree {
bottom: calc(var(--space-4) + 3rem + var(--space-2));
width: 2.5rem;
height: 2.5rem;
font-size: 1.1rem;
}
}
@media (max-width: 600px) {