Home: spread the activity table's slack, shorten its counts, shorten the fade

The trend column carried `w-full`, which made it swallow every spare pixel:
the five columns beside it huddled in the left 40% with a dead gap before the
curve. It takes a bounded third now, so the auto layout spreads the rest over
the columns that have content to show, and a long flow name still widens its
own column into the card's scroll.

`si` reaches the rollup counts it was written for — 179240 executions reads as
"179k", and the failure badge and the failures tile follow. The plain window
leaves the small ones alone: 615 is still 615. The standing counts (nodes,
flows running, queue depth) stay exact, as does everything acted on digit by
digit.

The fade ran a full 40 of the 100-unit box. In a table cell three times the
width of a panel that washed out readings still worth seeing, so it is 25 —
a hint at the left end rather than a quarter of the series.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XC2jX6Hdj7pxGGKzBTrbqB
This commit is contained in:
2026-08-17 11:38:07 +02:00
co-authored by Claude Opus 5
parent 64f57b732b
commit b9e67fa436
3 changed files with 25 additions and 10 deletions
+8 -2
View File
@@ -9,8 +9,14 @@ const PAD = 8
/** Above this ratio a linear series is all baseline and one spike. */
const LOG_RATIO = 100
/** How far the left end fades over, in viewBox units. */
const FADE = 40
/**
* How far the left end fades over, in viewBox units — a quarter of the width.
*
* Proportional, so it reads the same in a panel and in a table cell three
* times as wide. Any more and a wide curve loses readings that are still
* part of what the series says.
*/
const FADE = 25
/** Enough digits to tell two neighbouring readings apart. */
const READOUT_DIGITS = 4
@@ -113,7 +113,7 @@ export function HealthOverview() {
/>
<Tile
label="Failures (24h)"
value={String(summary?.failures_24h ?? 0)}
value={si(summary?.failures_24h ?? 0)}
note={
failures?.length
? `latest ${ago(failures[0].ts)}`
@@ -137,7 +137,7 @@ export function HealthOverview() {
<h2 className={PANEL_SECTION}>Flow activity (24h)</h2>
<div className={`${CARD} overflow-x-auto`}>
{/* The name anchors the left, the numbers read down their own
centre, and the trend takes whatever width is left over. */}
centre, and the trend closes the row on the right. */}
<table className="w-full text-sm">
<thead className="text-xs text-muted-foreground">
<tr>
@@ -148,7 +148,10 @@ export function HealthOverview() {
<th className="px-3 pb-2 text-center font-medium">Errors</th>
<th className="px-3 pb-2 text-center font-medium">Avg</th>
<th className="px-3 pb-2 text-center font-medium">Lag</th>
<th className="w-full min-w-32 pb-2 pl-3 text-right font-medium">
{/* A bounded share rather than all the slack: the columns
beside it grow with their own content, so the numbers
spread across the middle instead of huddling on the left. */}
<th className="w-1/3 min-w-32 pb-2 pl-3 text-right font-medium">
Trend
</th>
</tr>
@@ -165,10 +168,14 @@ export function HealthOverview() {
{row.flow || "—"}
</Link>
</td>
<td className="px-3 py-2 text-center">{row.executions}</td>
<td className="px-3 py-2 text-center">
{si(row.executions)}
</td>
<td className="px-3 py-2 text-center">
{row.errors ? (
<Badge variant="destructive">{row.errors} failed</Badge>
<Badge variant="destructive">
{si(row.errors)} failed
</Badge>
) : (
<span className="text-muted-foreground">none</span>
)}
+5 -3
View File
@@ -24,9 +24,11 @@ const SI_STEPS: [number, string][] = [
* keeps a reading in its column, and beyond giga or micro the exponent is.
*
* Where it applies: anything read at a glance and bounded by the width of a
* tile, a table cell, an axis gutter or a legend. Exact counts (executions,
* failures) and anything the user is about to act on — a payload, a form
* field, the edge inspector's value — stay unrounded.
* tile, a table cell, an axis gutter or a legend — a rollup's own counts
* included, since 179240 executions is a size, not a number anyone reads
* digit by digit. What the user acts on stays unrounded: a payload, a form
* field, the edge inspector's value, and the standing counts (nodes, flows
* running, queue depth) that are small by nature and exact by meaning.
*/
export function si(value: number, digits = 3): string {
if (!Number.isFinite(value)) return "--"