aboutsummaryrefslogtreecommitdiffstats
path: root/src/api/dashboard
diff options
context:
space:
mode:
authortv <tv@krebsco.de>2026-10-31 23:07:33 +0100
committertv <tv@krebsco.de>2026-10-31 23:07:33 +0100
commitafa42718cbf82b8b56f5962c7bd1318282acbea6 (patch)
treea30f2b192b3914786118f66b165506faca36dcd5 /src/api/dashboard
parent05ea71b3f69a0e2792519b84f7cc61df5c7056e1 (diff)
dashboard: allow right column to hide
Diffstat (limited to 'src/api/dashboard')
-rw-r--r--src/api/dashboard/dashboard.html45
1 files changed, 35 insertions, 10 deletions
diff --git a/src/api/dashboard/dashboard.html b/src/api/dashboard/dashboard.html
index ec36abf..6effc59 100644
--- a/src/api/dashboard/dashboard.html
+++ b/src/api/dashboard/dashboard.html
@@ -64,6 +64,10 @@
section.collapsed { align-self: start; }
section.collapsed h2 { margin: 0; }
section.collapsed h2 .toggle { display: none; }
+ /* The right column dragged off to the side: the map takes the width. */
+ @media (min-width: 901px) {
+ main.right-hidden > section:not(#map) { display: none; }
+ }
section h2 .what .id { color: var(--muted); font-weight: normal; word-break: break-all; }
/* The space between boxes, where they are resized. */
main.resize-columns, main.resize-columns * { cursor: col-resize; }
@@ -1193,9 +1197,13 @@ document.getElementById("document").replaceChildren(
// A box is busy while text in it is selected: drawing it anew would lose the selection,
// so it waits (`held`) until it's gone.
+// Collapsed, or not shown at all (the right column dragged off): drawn when opened
+// (`release`).
+function hidden(box) {
+ return box.classList.contains("collapsed") || box.getClientRects().length === 0;
+}
function busy(box) {
- // Collapsed: drawn when opened (`release`).
- if (box.classList.contains("collapsed")) return true;
+ if (hidden(box)) return true;
const selection = window.getSelection();
if (!selection || selection.isCollapsed || !selection.rangeCount) return false;
return box.contains(selection.getRangeAt(0).commonAncestorContainer);
@@ -1531,7 +1539,7 @@ function logTraffic(way, peer, total, kinds) {
(way === "sent" ? "→ " : "← ") + name(peer) + ": " + total + " (" + parts + ")"];
consoleLines.push(line);
if (consoleLines.length > CONSOLE_LINES) consoleLines.shift();
- if (document.getElementById("console-box").classList.contains("collapsed")) return;
+ if (hidden(document.getElementById("console-box"))) return;
const log = document.getElementById("console");
const scroll = document.getElementById("console-scroll");
const following = scroll.scrollTop + scroll.clientHeight >= scroll.scrollHeight - 4;
@@ -1683,16 +1691,25 @@ window.addEventListener("resize", () => { layoutAgain(); render(); });
// --- Sizes: the space between boxes dragged to resize them, double-clicked to reset;
// kept in this browser ---
const main = document.querySelector("main");
-// The map's share of the width; the peers' height in px; the console's share of what
-// the peers leave, and the figures' share of the rest. Null: as laid out by default.
+// The map's share of the width (1: the right column dragged off to the side, hidden);
+// the peers' height in px; the console's share of what the peers leave, and the
+// figures' share of the rest. Null: as laid out by default.
let sizes = { columns: null, peers: null, split: null, console: null };
try { sizes = { ...sizes, ...JSON.parse(localStorage.getItem("continuum-sizes") || "{}") }; }
catch (_) {}
function applySizes() {
const style = main.style;
+ const wasHidden = main.classList.contains("right-hidden");
+ main.classList.toggle("right-hidden", sizes.columns === 1);
if (sizes.columns === null) style.removeProperty("--columns");
+ else if (sizes.columns === 1) style.setProperty("--columns", "minmax(0, 1fr) 0");
else style.setProperty("--columns", "minmax(0, " + sizes.columns + "fr) minmax(0, " +
(1 - sizes.columns) + "fr)");
+ // Back: what waited is drawn.
+ if (wasHidden && sizes.columns !== 1) {
+ if (!hidden(document.getElementById("console-box"))) showConsole();
+ release();
+ }
// A collapsed box's row as tall as its title.
const shut = id => document.getElementById(id).classList.contains("collapsed");
const split = sizes.split === null ? .5 : sizes.split;
@@ -1708,9 +1725,12 @@ function applySizes() {
const box = id => document.getElementById(id).getBoundingClientRect();
// Which space between boxes `event` is over, if any: "columns", "peers" (below the
// peers), "split" (between figures and document) or "console" (above the console).
-// Only side by side.
+// Only side by side; with the right column hidden, right of the map: "columns".
function gapAt(event) {
if (event.target !== main) return null;
+ if (sizes.columns === 1 && main.classList.contains("right-hidden")) {
+ return event.clientX >= box("map").right ? "columns" : null;
+ }
const map = box("map"), peers = box("peers-box"), figures = box("figures-box"),
documentBox = box("document-box"), consoleBox = box("console-box");
if (map.right >= peers.left) return null;
@@ -1723,11 +1743,16 @@ function gapAt(event) {
}
function resizeTo(gap, event) {
const clamp = (value, low, high) => Math.min(high, Math.max(low, value));
- const half = (box("peers-box").left - box("map").right) / 2;
+ // The space between boxes (`main`'s gap), half of it each side.
+ const half = parseFloat(getComputedStyle(main).columnGap) / 2;
if (gap === "columns") {
- const map = box("map"), peers = box("peers-box");
- sizes.columns = clamp((event.clientX - half - map.left) / (peers.right - map.left - 2 * half),
- .2, .8);
+ // Across the whole width: the right column's right edge is `main`'s, inside.
+ const map = box("map");
+ const right = main.getBoundingClientRect().right -
+ parseFloat(getComputedStyle(main).paddingRight);
+ const share = (event.clientX - half - map.left) / (right - map.left - 2 * half);
+ // Dragged to the side: hidden.
+ sizes.columns = share > .9 ? 1 : clamp(share, .2, .8);
} else if (gap === "peers") {
const peers = box("peers-box"), consoleBox = box("console-box");
sizes.peers = Math.round(clamp(event.clientY - half - peers.top, 60,