@@ -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
3238export 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"];
290297const monthNames = [ "Jan" , "Feb" , "Mar" , "Apr" , "May" , "Jun" , "Jul" , "Aug" , "Sep" , "Oct" , "Nov" , "Dec" ] ;
291298
292299function 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