aboutsummaryrefslogtreecommitdiffstats
path: root/src/api/dashboard
diff options
context:
space:
mode:
authortv <tv@krebsco.de>2026-10-31 22:52:51 +0100
committertv <tv@krebsco.de>2026-10-31 22:52:51 +0100
commit120c3615d7c175d039513d328c02e4fbae242689 (patch)
tree485eda3b670b4f2e49457e96537d7bf18c206967 /src/api/dashboard
parent3c7e1d28eee39112b9cda47cd87c331e674218b5 (diff)
dashboard: updated labels breath
Diffstat (limited to 'src/api/dashboard')
-rw-r--r--src/api/dashboard/dashboard.html31
1 files changed, 25 insertions, 6 deletions
diff --git a/src/api/dashboard/dashboard.html b/src/api/dashboard/dashboard.html
index e584f48..ccf4892 100644
--- a/src/api/dashboard/dashboard.html
+++ b/src/api/dashboard/dashboard.html
@@ -597,6 +597,25 @@ function upright(attrs) {
function text(node, content) {
if (node.textContent !== content) node.textContent = content;
}
+// A label on the map: its text, breathing once when it changed (not when new), as the
+// connection's dot does: its underlay, in the shape of the new text, glows and fades.
+// An animation of its own, not a class: every render sets the label's attributes.
+const calm = matchMedia("(prefers-reduced-motion: reduce)");
+function label(node, content) {
+ if (node.textContent === content) return;
+ const before = node.textContent;
+ node.textContent = content;
+ if (!before || calm.matches || !node.animate) return;
+ const colours = getComputedStyle(document.documentElement);
+ const panel = colours.getPropertyValue("--panel").trim();
+ const glow = "color-mix(in srgb, " + colours.getPropertyValue("--self").trim() + " 45%, " +
+ panel + ")";
+ node.animate([
+ { stroke: panel, strokeWidth: "4px" },
+ { stroke: glow, strokeWidth: "7px", offset: .3 },
+ { stroke: panel, strokeWidth: "4px" },
+ ], { duration: 900, easing: "ease-in-out" });
+}
// A tooltip whose text changes under the pointer goes and comes back (the ages in it
// change on every render): its new text waits until the pointer leaves.
const tooltipsDue = new WeakMap();
@@ -742,13 +761,13 @@ function renderGraph() {
const along = Math.min(length / 2, Math.max(36, length * .3));
const t = (line.used ? along : Math.max(24, along * .6)) / length;
const out = line.used ? -4 : Math.sign(side) * 9;
- const label = drawing("rtt " + key + " " + i, "text", upright({
+ const rtt = drawing("rtt " + key + " " + i, "text", upright({
x: p.x + (q.x - p.x) * t + ox + nx * out,
y: p.y + (q.y - p.y) * t + oy + ny * out + (line.used ? 0 : 3),
"text-anchor": "middle", "font-size": line.used ? 11 : 9,
fill: line.used ? "var(--fg)" : "var(--muted)" }));
- text(label, ms(line.rttMs));
- labels.push(label);
+ label(rtt, ms(line.rttMs));
+ labels.push(rtt);
}
});
tooltip(covering, descriptions.join("\n"));
@@ -792,10 +811,10 @@ function renderGraph() {
const pin = pinned.has(id) ? [drawing("pin " + id, "circle", { cx: p.x, cy: p.y, r: 2,
fill: member.self || reported ? "var(--panel)" : "var(--fg)",
"pointer-events": "none" })] : [];
- const label = drawing("name " + id, "text", upright({ x: p.x + 10, y: p.y + 4,
+ const nameLabel = drawing("name " + id, "text", upright({ x: p.x + 10, y: p.y + 4,
"font-size": 12, fill: "var(--fg)", cursor: "pointer" }), pressed);
- text(label, name(id));
- children.push(circle, ...pin, label);
+ label(nameLabel, name(id));
+ children.push(circle, ...pin, nameLabel);
}
show(document.getElementById("view"), children);
}