diff options
| author | tv <tv@krebsco.de> | 2026-11-02 16:57:15 +0100 |
|---|---|---|
| committer | tv <tv@krebsco.de> | 2026-11-02 16:57:15 +0100 |
| commit | 611361e0405485b85d7de5ad37509c1d1981f05f (patch) | |
| tree | 81625652ee40a48cb249eed7410f2ecf8b351ec4 | |
| parent | 3f5868f54a7d5dac48abbd7ac5ec35cacbebc182 (diff) | |
dashboard: focus wins over hover
| -rw-r--r-- | docs/dashboard.md | 6 | ||||
| -rw-r--r-- | src/api/dashboard/dashboard.html | 53 |
2 files changed, 35 insertions, 24 deletions
diff --git a/docs/dashboard.md b/docs/dashboard.md index 14834bc..84d19c8 100644 --- a/docs/dashboard.md +++ b/docs/dashboard.md @@ -244,11 +244,13 @@ does an ordinary SYNC. The map marks the message's two nodes and the link between them in the grey its line has in the console, each in its own shape: a circle around each node, and the link's -lines as they bow. The message pointed at is marked, else the one shown. +lines as they bow. The message shown and the one pointed at are both marked, each in +its line's grey; where they mark the same node or link, the shown one's wins. The other way round, the messages exchanged with a node, or over one of this node's links, are tinted in the colour of its halo on the map: lightly while it is pointed at -there, stronger while it is in focus (clicked there or in the peers). +there, stronger while it is in focus (clicked there or in the peers); where both tint a +message, in focus wins. ## While you read diff --git a/src/api/dashboard/dashboard.html b/src/api/dashboard/dashboard.html index 65432bd..1b9a8cb 100644 --- a/src/api/dashboard/dashboard.html +++ b/src/api/dashboard/dashboard.html @@ -102,11 +102,11 @@ /* Of one exchange with the message pointed at or shown (`related`): a lighter grey, and the bar. */ /* Exchanged with the node or over the link pointed at on the map, or in focus: the - colour of its halo. */ - .console > div.peer-focused { - background: color-mix(in srgb, var(--self) calc(var(--halo-focused) * 100%), transparent); } + colour of its halo; in focus wins. */ .console > div.peer-hovered { background: color-mix(in srgb, var(--self) calc(var(--halo-hovered) * 100%), transparent); } + .console > div.peer-focused { + background: color-mix(in srgb, var(--self) calc(var(--halo-focused) * 100%), transparent); } .console > div.related { background: rgba(127, 127, 127, .08); border-left-color: var(--self); } .console > div:hover { background: rgb(127 127 127 / var(--pointed)); } .console > div.focused { background: rgb(127 127 127 / var(--shown)); } @@ -814,19 +814,29 @@ function renderGraph() { settle(); } const children = []; - // Under everything: the nodes and the link of the message pointed at in the console, - // else of the one shown, in the grey its line has there, each in its own shape (the - // lines of a link as they bow, a node's circle). One group, so where they overlap - // the grey is no darker. - const message = pointedMessage || shownMessage; - const marks = drawing("marks", "g", { "pointer-events": "none", - style: "opacity: var(" + (pointedMessage ? "--pointed" : "--shown") + ")" }); - const marked = []; - const markedKey = message ? pairKey(state.node.id, message.peer) : null; - const mark = (tag, attrs) => marked.push(svg(tag, attrs)); - const markLine = (d, width) => mark("path", { d, fill: "none", stroke: "rgb(127 127 127)", - "stroke-width": width + 8, "stroke-linecap": "round" }); - children.push(marks); + // Under everything: the nodes and the link of the message shown in the console, and + // of the one pointed at, each in the grey its line has there (the shown one's where + // both mark the same), in its own shape (the lines of a link as they bow, a node's + // circle). A group per grey, so where its shapes overlap it is no darker. + const marking = new Map(); + for (const [message, how] of [[pointedMessage, "pointed"], [shownMessage, "shown"]]) { + if (message === null) continue; + for (const key of [state.node.id, message.peer, pairKey(state.node.id, message.peer)]) { + marking.set(key, how); + } + } + const marks = Object.fromEntries(["pointed", "shown"].map(how => [how, + drawing("marks " + how, "g", { "pointer-events": "none", + style: "opacity: var(--" + how + ")" })])); + const marked = { pointed: [], shown: [] }; + // A shape under `key` (a node's ID, a link's pair key), if it is marked. + const mark = (key, tag, attrs) => { + const how = marking.get(key); + if (how) marked[how].push(svg(tag, attrs)); + }; + const markLine = (key, d, width) => mark(key, "path", { d, fill: "none", + stroke: "rgb(127 127 127)", "stroke-width": width + 8, "stroke-linecap": "round" }); + children.push(marks.pointed, marks.shown); // Behind a link: a halo while it's hovered or in focus (`width`: of its lines). const halo = (key, p, q, width) => { if (key !== hovered && key !== focused) return; @@ -853,7 +863,7 @@ function renderGraph() { if (measured.has(key)) continue; const p = positions.get(a), q = positions.get(b); halo(key, p, q, 1); - if (key === markedKey) markLine("M " + p.x + " " + p.y + " L " + q.x + " " + q.y, 1); + markLine(key, "M " + p.x + " " + p.y + " L " + q.x + " " + q.y, 1); children.push(drawing("intended " + key, "line", { x1: p.x, y1: p.y, x2: q.x, y2: q.y, stroke: "var(--intended)", "stroke-dasharray": "4 4", "stroke-width": 1 })); tooltip(hit(key, p, q, 1), name(a) + " – " + name(b) + ": intended (member list), not measured"); @@ -903,7 +913,7 @@ function renderGraph() { } else if (line.used ? link.relayed : line.relayed) { attrs["stroke-dasharray"] = "7 4"; } - if (key === markedKey) markLine(attrs.d, attrs["stroke-width"]); + markLine(key, attrs.d, attrs["stroke-width"]); const drawnLine = drawing("path " + key + " " + i, "path", attrs); const description = name(a) + " – " + name(b) + (line.transport ? " via " + line.transport : "") + (line.used ? " (in use)" : "") + @@ -961,9 +971,7 @@ function renderGraph() { // Dormant as this node sees it (`/peers`): a red outline. const dormant = (state.peers.peers[id] || {}).status === "dormant"; const radius = member.self ? 8 : 6; - if (message && (id === state.node.id || id === message.peer)) { - mark("circle", { cx: p.x, cy: p.y, r: radius + 6, fill: "rgb(127 127 127)" }); - } + mark(id, "circle", { cx: p.x, cy: p.y, r: radius + 6, fill: "rgb(127 127 127)" }); const circle = drawing("node " + id, "circle", { cx: p.x, cy: p.y, r: radius, fill: member.self ? "var(--self)" : reported ? "var(--fg)" : "var(--panel)", stroke: member.self ? "var(--self)" : dormant ? "var(--bad)" : "var(--fg)", @@ -983,7 +991,8 @@ function renderGraph() { label(nameLabel, name(id)); children.push(circle, ...pin, nameLabel); } - marks.replaceChildren(...marked); + marks.pointed.replaceChildren(...marked.pointed); + marks.shown.replaceChildren(...marked.shown); show(document.getElementById("view"), children); } |
