Skip to content

Commit 0a50b79

Browse files
committed
Refine request heatmap color scale
1 parent ded38e2 commit 0a50b79

1 file changed

Lines changed: 36 additions & 18 deletions

File tree

web/src/components/HealthGrid.tsx

Lines changed: 36 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,21 @@ interface YearCell {
1818
future: boolean;
1919
}
2020

21-
function cellTone(total: number, failed: number, maxTotal: number): string {
21+
function cellTone(total: number, maxTotal: number): string {
2222
if (total === 0) return "bg-panel2";
23-
const failRate = failed / total;
24-
if (failRate >= 0.5) return "bg-danger/80";
25-
if (failRate > 0) return "bg-warn/70";
2623
const intensity = maxTotal > 0 ? total / maxTotal : 0;
27-
if (intensity >= 0.66) return "bg-success";
28-
if (intensity >= 0.33) return "bg-success/70";
29-
return "bg-success/40";
24+
if (intensity >= 0.75) return "bg-success";
25+
if (intensity >= 0.5) return "bg-success/80";
26+
if (intensity >= 0.25) return "bg-success/60";
27+
return "bg-success/35";
28+
}
29+
30+
function failureMarker(total: number, failed: number): string {
31+
if (total === 0 || failed === 0) return "";
32+
const failRate = failed / total;
33+
if (failRate >= 0.5) return "ring-1 ring-danger";
34+
if (failRate >= 0.1) return "ring-1 ring-warn";
35+
return "ring-1 ring-success/45";
3036
}
3137

3238
export default function HealthGrid({ health, filter, selectedDay, onYearChange, onDaySelect }: Props) {
@@ -130,7 +136,7 @@ function YearDayCell({
130136
onClick={() => onSelect(cell.key)}
131137
className={clsx(
132138
"h-5 w-5 rounded-[3px] transition-shadow focus:outline-none focus:ring-1 focus:ring-accent",
133-
cell.future ? "bg-panel2/40 opacity-50" : cellTone(total, failed, maxTotal),
139+
cell.future ? "bg-panel2/40 opacity-50" : [cellTone(total, maxTotal), failureMarker(total, failed)],
134140
!cell.future && "hover:ring-1 hover:ring-accent",
135141
selected && "ring-1 ring-accent",
136142
)}
@@ -167,14 +173,15 @@ function DayDetail({ day, grid, filter }: { day: string; grid: HealthCell[][]; f
167173
to={{ pathname: "/events", search: eventSearch(cell, filter, 5) }}
168174
className={clsx(
169175
"block h-5 w-5 rounded-[3px] transition-shadow hover:ring-1 hover:ring-accent focus:outline-none focus:ring-1 focus:ring-accent",
170-
cellTone(cell.total, cell.failed, maxTotal),
176+
cellTone(cell.total, maxTotal),
177+
failureMarker(cell.total, cell.failed),
171178
)}
172179
title={title}
173180
aria-label={`Open events for ${title}`}
174181
/>
175182
) : (
176183
<div
177-
className={clsx("h-5 w-5 rounded-[3px]", cellTone(cell.total, cell.failed, maxTotal))}
184+
className={clsx("h-5 w-5 rounded-[3px]", cellTone(cell.total, maxTotal), failureMarker(cell.total, cell.failed))}
178185
title={title}
179186
/>
180187
)}
@@ -290,17 +297,28 @@ const weekdayLabels = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
290297
const monthNames = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
291298

292299
function Legend() {
293-
const items = [
300+
const volumeItems = [
294301
{ tone: "bg-panel2", label: "no traffic" },
295-
{ tone: "bg-success/40", label: "less" },
296-
{ tone: "bg-success/70", label: "more" },
297-
{ tone: "bg-success", label: "most" },
298-
{ tone: "bg-warn/70", label: "some failures" },
299-
{ tone: "bg-danger/80", label: "many failures" },
302+
{ tone: "bg-success/35", label: "low" },
303+
{ tone: "bg-success/60", label: "medium" },
304+
{ tone: "bg-success/80", label: "high" },
305+
{ tone: "bg-success", label: "peak" },
306+
];
307+
const failureItems = [
308+
{ tone: "bg-panel2 ring-1 ring-success/45", label: "<10% failed" },
309+
{ tone: "bg-panel2 ring-1 ring-warn", label: ">=10% failed" },
310+
{ tone: "bg-panel2 ring-1 ring-danger", label: ">=50% failed" },
300311
];
301312
return (
302-
<div className="flex items-center gap-3 text-[11px] text-muted">
303-
{items.map((i) => (
313+
<div className="flex flex-wrap items-center gap-3 text-[11px] text-muted">
314+
{volumeItems.map((i) => (
315+
<div key={i.label} className="flex items-center gap-1">
316+
<span className={clsx("inline-block w-3 h-3 rounded-sm", i.tone)} />
317+
<span>{i.label}</span>
318+
</div>
319+
))}
320+
<span className="text-border">|</span>
321+
{failureItems.map((i) => (
304322
<div key={i.label} className="flex items-center gap-1">
305323
<span className={clsx("inline-block w-3 h-3 rounded-sm", i.tone)} />
306324
<span>{i.label}</span>

0 commit comments

Comments
 (0)