Rate monitor: peak-hold tick on the equalizer bars (the VU idiom)

A thin accent marker sticks at each bar's recent maximum, holds ~1.2s, then
falls a few percent per update until it rests on the live fill — exactly how a
hardware VU meter's peak LED behaves. A traffic burst stays readable for a few
seconds after it's over instead of vanishing with the next 1s sample. Hidden
while it sits on the fill so idle bars don't carry a stray line.
This commit is contained in:
BoulderBadgeDad 2026-06-06 15:40:49 -07:00
parent 01ae63f0d5
commit 12ad373a83
2 changed files with 45 additions and 1 deletions

View file

@ -236,6 +236,7 @@ function _renderEqualizerBars(grid, data) {
<div class="rate-eq-shimmer"></div>
<div class="rate-eq-tip"></div>
</div>
<div class="rate-eq-peak"></div>
<div class="rate-eq-value">0</div>
</div>
<div class="rate-eq-meta">
@ -275,6 +276,26 @@ function _renderEqualizerBars(grid, data) {
const fill = bar.querySelector('.rate-eq-fill');
if (fill) fill.style.height = `${pct * 100}%`;
// Peak-hold tick — the VU-meter idiom: a thin marker sticks at the
// recent maximum, holds ~1.2s, then falls a few %/update until it
// rests on the live fill. A burst stays readable after it's over.
const nowTs = performance.now();
let peak = prev.peak ?? pct;
let peakAt = prev.peakAt ?? nowTs;
if (pct >= peak) {
peak = pct;
peakAt = nowTs;
} else if (nowTs - peakAt > 1200) {
peak = Math.max(pct, peak - 0.045);
}
const peakEl = bar.querySelector('.rate-eq-peak');
if (peakEl) {
peakEl.style.bottom = `${peak * 100}%`;
// Only show while meaningfully above the live fill — idle bars
// shouldn't carry a stray line.
peakEl.classList.toggle('visible', peak > pct + 0.015 && peak > 0.06);
}
// The reflection puddle (CSS ::after on the track) fades in
// proportional to the real (unclamped) rate so idle services
// don't pollute the row with a floor of glow. Bound to a
@ -329,7 +350,7 @@ function _renderEqualizerBars(grid, data) {
bar.classList.toggle('active', value > 0 || wStatus === 'running');
bar.classList.toggle('rate-limited', isRateLimited);
_eqDisplay[svc] = { value, pct };
_eqDisplay[svc] = { value, pct, peak, peakAt };
}
}

View file

@ -63242,6 +63242,29 @@ body.reduce-effects .dash-card::after {
opacity: 0.85;
}
/* Peak-hold tick sticks at the recent maximum and slowly falls, like a
* hardware VU meter's peak LED. Position (bottom %) is driven from JS;
* only visible while it's meaningfully above the live fill so idle bars
* don't carry a stray line. */
.rate-eq-peak {
position: absolute;
left: 10%;
right: 10%;
bottom: 4%;
height: 2px;
border-radius: 1px;
background: color-mix(in srgb, var(--eq-accent) 55%, white 45%);
box-shadow: 0 0 6px color-mix(in srgb, var(--eq-accent) 70%, transparent);
opacity: 0;
transition: bottom 0.9s linear, opacity 0.4s;
pointer-events: none;
z-index: 2;
}
.rate-eq-peak.visible {
opacity: 0.75;
}
/* Vertical shimmer scan — runs continuously when active */
.rate-eq-shimmer {
position: absolute;