From 868cf84c4e80a8422d624c2ffc6f14ddeffe52f4 Mon Sep 17 00:00:00 2001 From: hsiegeln <37154749+hsiegeln@users.noreply.github.com> Date: Fri, 13 Mar 2026 18:38:49 +0100 Subject: [PATCH] Trim first and last sparkline data points to avoid partial bucket skew Co-Authored-By: Claude Opus 4.6 --- ui/src/components/shared/Sparkline.tsx | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/ui/src/components/shared/Sparkline.tsx b/ui/src/components/shared/Sparkline.tsx index fed0a463..c6583cde 100644 --- a/ui/src/components/shared/Sparkline.tsx +++ b/ui/src/components/shared/Sparkline.tsx @@ -8,17 +8,20 @@ interface SparklineProps { export function Sparkline({ data, color }: SparklineProps) { const gradientId = useId(); + // Drop first and last buckets — they are partial time windows and skew the trend + const trimmed = useMemo(() => (data.length > 4 ? data.slice(1, -1) : data), [data]); + const { linePath, fillPath } = useMemo(() => { - if (data.length < 2) return { linePath: '', fillPath: '' }; + if (trimmed.length < 2) return { linePath: '', fillPath: '' }; const w = 200; const h = 24; - const max = Math.max(...data); - const min = Math.min(...data); + const max = Math.max(...trimmed); + const min = Math.min(...trimmed); const range = max - min || 1; - const step = w / (data.length - 1); + const step = w / (trimmed.length - 1); - const points = data.map( + const points = trimmed.map( (v, i) => `${i * step},${h - ((v - min) / range) * (h - 2) - 1}`, ); @@ -26,9 +29,9 @@ export function Sparkline({ data, color }: SparklineProps) { linePath: points.join(' '), fillPath: `0,${h} ${points.join(' ')} ${w},${h}`, }; - }, [data]); + }, [trimmed]); - if (data.length < 2) return null; + if (trimmed.length < 2) return null; return (