Merge TOC into page content
This commit is contained in:
+1
-1
@@ -48,7 +48,7 @@
|
|||||||
</span>
|
</span>
|
||||||
</footer>
|
</footer>
|
||||||
</div>
|
</div>
|
||||||
{{if not .EditMode}}<aside class="sidebar">{{block "sidebar" .}}{{end}}</aside>{{end}}
|
{{if not .EditMode}}{{block "aside" .}}{{end}}{{end}}
|
||||||
</div>
|
</div>
|
||||||
{{block "extras" .}}{{end}}
|
{{block "extras" .}}{{end}}
|
||||||
</body>
|
</body>
|
||||||
|
|||||||
+2
-4
@@ -1,8 +1,6 @@
|
|||||||
// Full-viewport Overlay component (mobile). Distinct from the .modal dialog:
|
// Full-viewport Overlay component (mobile). Distinct from the .modal dialog:
|
||||||
// this hosts a whole rail (the folder tree or the right-rail widgets/TOC) at
|
// this hosts a whole sidebar at full screen with its own scroll and a top-right close control.
|
||||||
// full screen with its own scroll and a top-right close control. It reuses the
|
// It reuses the low-level focus/Escape/bfcache patterns from modal.js rather than that component's panel chrome.
|
||||||
// low-level focus/Escape/bfcache patterns from modal.js rather than that
|
|
||||||
// component's panel chrome.
|
|
||||||
//
|
//
|
||||||
// openOverlay(node) MOVES `node` (an existing rail <aside>) into the overlay
|
// openOverlay(node) MOVES `node` (an existing rail <aside>) into the overlay
|
||||||
// body and restores it to its original DOM position on close, so the rail keeps
|
// body and restores it to its original DOM position on close, so the rail keeps
|
||||||
|
|||||||
@@ -66,4 +66,4 @@
|
|||||||
<script src="/_/page/sidebar-fab.js"></script>
|
<script src="/_/page/sidebar-fab.js"></script>
|
||||||
{{end}}
|
{{end}}
|
||||||
|
|
||||||
{{define "sidebar"}}{{if .SidebarWidget}}{{.SidebarWidget}}{{end}}{{end}}
|
{{define "aside"}}{{if .SidebarWidget}}<aside class="sidebar">{{.SidebarWidget}}</aside>{{end}}{{end}}
|
||||||
|
|||||||
@@ -1,8 +1,3 @@
|
|||||||
// Mobile: the right-rail FAB is stacked ABOVE the tree FAB and opens the right
|
|
||||||
// rail (TOC + page widgets) in the full-viewport Overlay (overlay.js). It only
|
|
||||||
// appears when the rail actually has content — runs after toc.js has had a
|
|
||||||
// chance to populate the rail (script order in page/main.html), so an
|
|
||||||
// otherwise-empty rail shows no FAB. Hidden on desktop by .fab CSS.
|
|
||||||
document.addEventListener("DOMContentLoaded", function () {
|
document.addEventListener("DOMContentLoaded", function () {
|
||||||
var aside = document.querySelector("aside.sidebar");
|
var aside = document.querySelector("aside.sidebar");
|
||||||
if (!aside || !aside.children.length) return;
|
if (!aside || !aside.children.length) return;
|
||||||
|
|||||||
+2
-4
@@ -6,7 +6,7 @@ document.addEventListener("DOMContentLoaded", function () {
|
|||||||
if (headings.length < 2) return;
|
if (headings.length < 2) return;
|
||||||
|
|
||||||
var nav = document.createElement("nav");
|
var nav = document.createElement("nav");
|
||||||
nav.className = "toc panel panel-sidebar";
|
nav.className = "toc panel";
|
||||||
|
|
||||||
var header = document.createElement("div");
|
var header = document.createElement("div");
|
||||||
header.className = "panel-header";
|
header.className = "panel-header";
|
||||||
@@ -28,7 +28,5 @@ document.addEventListener("DOMContentLoaded", function () {
|
|||||||
});
|
});
|
||||||
nav.appendChild(list);
|
nav.appendChild(list);
|
||||||
|
|
||||||
// Stack the TOC on top of any server-rendered widget(s) already in the rail.
|
content.insertBefore(nav, content.firstChild);
|
||||||
var rail = document.querySelector("aside.sidebar");
|
|
||||||
rail.insertBefore(nav, rail.firstChild);
|
|
||||||
});
|
});
|
||||||
|
|||||||
+14
-26
@@ -597,12 +597,7 @@ button.fab { display: none; }
|
|||||||
::-webkit-scrollbar-thumb { background: var(--primary); }
|
::-webkit-scrollbar-thumb { background: var(--primary); }
|
||||||
::-webkit-scrollbar-thumb:hover { background: var(--primary-hover); }
|
::-webkit-scrollbar-thumb:hover { background: var(--primary-hover); }
|
||||||
|
|
||||||
/* === Sidebar (right rail) ===
|
/* === Optional Sidebar (right side) === */
|
||||||
Full-height column in the app-shell that scrolls its own overflow (TOC on
|
|
||||||
top, page widget(s) below). Collapses out of the flex row when it has no
|
|
||||||
content so the center column widens. A dashed separator to main mirrors the
|
|
||||||
left tree rail; widgets within drop their panel outlines (see
|
|
||||||
.panel-sidebar). */
|
|
||||||
.sidebar {
|
.sidebar {
|
||||||
width: 14rem;
|
width: 14rem;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
@@ -614,21 +609,23 @@ button.fab { display: none; }
|
|||||||
border-left: var(--border-dashed);
|
border-left: var(--border-dashed);
|
||||||
}
|
}
|
||||||
aside.sidebar:empty { display: none; }
|
aside.sidebar:empty { display: none; }
|
||||||
|
|
||||||
/* Density modifier for panels in the sidebar (smaller font, tighter padding).
|
|
||||||
Drops the .panel outline so the rail reads as a clean column separated from
|
|
||||||
main by the .sidebar dashed border, matching the left tree rail. Inside the
|
|
||||||
mobile Overlay the widgets render as plain full-width content. */
|
|
||||||
.panel-sidebar {
|
.panel-sidebar {
|
||||||
padding: var(--space-2) var(--space-3);
|
padding: var(--space-2) var(--space-3);
|
||||||
font-size: var(--font-sm);
|
font-size: var(--font-sm);
|
||||||
border: none;
|
border: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* === Table of contents ===
|
/* === Table of contents ===*/
|
||||||
Rendered as a .panel-sidebar block in the right rail (padding + font-size
|
.toc {
|
||||||
come from that density class); toc.js always mounts it there, on both
|
float: right;
|
||||||
desktop and inside the mobile Overlay. */
|
width: 15rem;
|
||||||
|
max-width: 45%;
|
||||||
|
margin: 0 0 var(--space-3) var(--space-4);
|
||||||
|
padding: var(--space-2) var(--space-3);
|
||||||
|
font-size: var(--font-sm);
|
||||||
|
max-width: 60vh;
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
.toc ul { list-style: none; margin: 0; padding: 0; }
|
.toc ul { list-style: none; margin: 0; padding: 0; }
|
||||||
.toc li { margin: 0.15rem 0; }
|
.toc li { margin: 0.15rem 0; }
|
||||||
.toc a {
|
.toc a {
|
||||||
@@ -889,10 +886,6 @@ aside.sidebar:empty { display: none; }
|
|||||||
main { padding: var(--space-4) var(--space-3); }
|
main { padding: var(--space-4) var(--space-3); }
|
||||||
.app-name {display: none;}
|
.app-name {display: none;}
|
||||||
.editor-cm { min-height: 50vh; }
|
.editor-cm { min-height: 50vh; }
|
||||||
/* Editing on mobile is full-bleed: drop the main inset so the toolbar and
|
|
||||||
editor use the entire viewport width. */
|
|
||||||
body.edit-mode main { padding: 0; }
|
|
||||||
/* Fingers, not cursors: give every toolbar control a ~44px tap target. */
|
|
||||||
.editor-toolbar { gap: var(--space-2); padding: var(--space-2); }
|
.editor-toolbar { gap: var(--space-2); padding: var(--space-2); }
|
||||||
.editor-toolbar .btn-tool {
|
.editor-toolbar .btn-tool {
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
@@ -902,17 +895,10 @@ aside.sidebar:empty { display: none; }
|
|||||||
min-height: 2rem;
|
min-height: 2rem;
|
||||||
padding: 0 var(--space-1);
|
padding: 0 var(--space-1);
|
||||||
}
|
}
|
||||||
/* Pin the toolbar above the on-screen keyboard rather than at the top, which
|
|
||||||
is out of thumb reach while typing. interactive-widget=resizes-content
|
|
||||||
(layout.html viewport) shrinks the viewport on keyboard open so bottom: 0
|
|
||||||
sits directly above it. cm-content reserves matching scroll space so the
|
|
||||||
last lines aren't hidden behind the bar. */
|
|
||||||
body.edit-mode .editor-toolbar {
|
body.edit-mode .editor-toolbar {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
left: 0;
|
left: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
/* Reset the desktop sticky `top: 0`; with it, fixed + top + bottom would
|
|
||||||
stretch the bar to the full viewport height. */
|
|
||||||
top: auto;
|
top: auto;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
z-index: 50;
|
z-index: 50;
|
||||||
@@ -923,6 +909,7 @@ aside.sidebar:empty { display: none; }
|
|||||||
body.edit-mode .cm-content {
|
body.edit-mode .cm-content {
|
||||||
padding-bottom: calc(5rem + env(safe-area-inset-bottom));
|
padding-bottom: calc(5rem + env(safe-area-inset-bottom));
|
||||||
}
|
}
|
||||||
|
body.edit-mode main { padding: 0; }
|
||||||
.modal-backdrop { padding: var(--space-2); align-items: flex-start; }
|
.modal-backdrop { padding: var(--space-2); align-items: flex-start; }
|
||||||
.modal { max-width: none; margin-top: var(--space-4); }
|
.modal { max-width: none; margin-top: var(--space-4); }
|
||||||
.modal .panel-header { cursor: default; }
|
.modal .panel-header { cursor: default; }
|
||||||
@@ -938,4 +925,5 @@ aside.sidebar:empty { display: none; }
|
|||||||
.list-item td.icon { grid-row: 1; grid-column: 1; }
|
.list-item td.icon { grid-row: 1; grid-column: 1; }
|
||||||
.list-item td.name { grid-row: 1; grid-column: 2; }
|
.list-item td.name { grid-row: 1; grid-column: 2; }
|
||||||
.list-item td.meta { grid-row: 2; grid-column: 2; text-align: left; }
|
.list-item td.meta { grid-row: 2; grid-column: 2; text-align: left; }
|
||||||
|
.toc {float: none; width: auto; max-width: none; margin: 0 0 var(--space-4);}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user