todo.txt integration

This commit is contained in:
2026-07-03 11:08:27 +02:00
parent 8c9b448bdc
commit 5e72b073b8
9 changed files with 458 additions and 36 deletions
+68 -9
View File
@@ -99,8 +99,8 @@ hr { border: none; border-top: var(--border-dashed); margin: var(--space-4) 0; }
The shell is a full-height flex row below the header: left rail | center |
right rail. Each column owns its own vertical scroll (overflow-y:auto +
min-height:0), so nothing scrolls the page as a whole. Edge-to-edge: no
centered max-width container. Either rail collapses out of the flex flow when
empty (:empty { display:none }), letting the center reclaim the width. */
centered max-width container. The right rail collapses out of the flex flow
when empty (:empty { display:none }), letting the center reclaim the width. */
.shell {
display: flex;
min-height: 0;
@@ -465,6 +465,9 @@ body.edit-mode footer { max-width: none; }
.fab { position: fixed; bottom: var(--space-4); right: var(--space-4); z-index: 50; }
button.fab { display: none; }
.fab-rail { bottom: calc(var(--space-4) + 3rem + var(--space-2)); }
/* Todo FAB: third slot, above the tree and right-rail FABs. Only created when
todo.txt exists (todo-rail.js). */
.fab-todo { bottom: calc(var(--space-4) + 2 * (3rem + var(--space-2))); }
/* === Companion status === */
.companion-status { margin-left: auto; }
@@ -664,7 +667,7 @@ aside.sidebar:empty { display: none; }
padding: var(--space-3) var(--space-4);
-webkit-overflow-scrolling: touch;
}
.overlay-body .tree-sidebar,
.overlay-body .tree-scroll,
.overlay-body .sidebar {
display: block;
width: auto;
@@ -673,6 +676,11 @@ aside.sidebar:empty { display: none; }
padding: 0;
overflow: visible;
}
/* The todo widget fills the overlay: drop the rail divider and lift the
internal height cap so the whole file is editable on mobile. */
.overlay-body .todo-rail { border-bottom: none; padding-bottom: 0; }
.overlay-body .todo-rail .todo-rail-view,
.overlay-body .todo-rail .cm-editor { max-height: none; }
/* Right rail keeps its column spacing (TOC above widgets) inside the overlay;
the base .sidebar already sets flex-direction + gap. */
.overlay-body .sidebar { display: flex; }
@@ -723,21 +731,72 @@ aside.sidebar:empty { display: none; }
/* === Tree sidebar (persistent left navigation rail) ===
Reuses the .tree-row / .tree-children / .tree-name / .tree-chevron modules.
Desktop: a full-height column in the app-shell that scrolls its own
overflow. Mobile: not laid out inline — its content is surfaced through the
Overlay via .fab-tree (see responsive). */
Desktop: a full-height flex column in the app-shell (composes with .col)
holding the todo widget pinned on top and the tree's own scroll region
below. Mobile: not laid out inline — its content is surfaced through the
Overlay via the stacked FABs (see responsive). */
/* No right padding on the aside: the scrolling children below reach the
border-right so their scrollbars sit flush against the divider line (they
pad their own content off the scrollbar instead). */
.tree-sidebar {
width: var(--tree-width);
flex-shrink: 0;
overflow-y: auto;
padding: var(--space-4) var(--space-2) var(--space-4) var(--space-4);
min-height: 0;
padding: var(--space-4) 0 var(--space-4) var(--space-4);
border-right: var(--border-dashed);
}
/* The tree's scroll region: only the tree overflows, the todo widget above
keeps its own internal scroll. Also the node the tree FAB moves into the
Overlay, so font sizing lives here rather than on the aside. */
.tree-scroll {
flex: 1 1 auto;
min-height: 0;
overflow-y: auto;
padding-right: var(--space-2);
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; }
/* === Todo rail (root todo.txt widget) ===
Pinned above the folder tree (todo-rail.js). Hidden via the [hidden]
attribute until GET /_todo confirms the file exists. A long file scrolls
internally rather than pushing the tree off screen; the height cap is
lifted inside the Overlay. */
.todo-rail {
flex-shrink: 0;
padding-bottom: var(--space-3);
border-bottom: var(--border-dashed);
}
.todo-rail-head {
font-size: var(--font-xs);
margin-bottom: var(--space-2);
padding-right: var(--space-2);
}
.todo-unsaved { color: var(--primary-hover); font-size: var(--font-xs); }
/* The scrolling children run edge-to-edge (the aside has no right padding) so
their scrollbars are flush with the divider; padding-right keeps their text
clear of the scrollbar. */
.todo-rail-view {
font-family: "Iosevka Slab", monospace;
font-size: var(--font-xs);
line-height: 1.5;
white-space: pre-wrap;
word-break: break-word;
max-height: 40vh;
overflow-y: auto;
padding-right: var(--space-2);
cursor: text;
}
.todo-rail .cm-editor { max-height: 40vh; }
.todo-rail .cm-content { padding-right: var(--space-2); }
.todo-rail .todo-fallback {
width: 100%;
min-height: 10rem;
font-family: "Iosevka Slab", monospace;
font-size: var(--font-xs);
}
/* === Movie info box === */
.movie-info { margin: var(--space-3) 0; }