From bb92113fa48a23275586df9ea75f1e40aecd5464 Mon Sep 17 00:00:00 2001 From: Matt Aitken Date: Wed, 18 Feb 2026 16:34:34 +0000 Subject: [PATCH] Fix for stale data when hovering --- .../primitives/charts/ChartLegendCompound.tsx | 37 +++++++++---------- 1 file changed, 18 insertions(+), 19 deletions(-) diff --git a/apps/webapp/app/components/primitives/charts/ChartLegendCompound.tsx b/apps/webapp/app/components/primitives/charts/ChartLegendCompound.tsx index ddffdc4575..d0811b3b95 100644 --- a/apps/webapp/app/components/primitives/charts/ChartLegendCompound.tsx +++ b/apps/webapp/app/components/primitives/charts/ChartLegendCompound.tsx @@ -74,12 +74,12 @@ export function ChartLegendCompound({ const currentTotal = useMemo((): number | null => { if (!activePayload?.length) return grandTotal; - // Collect all series values from the hovered data point, preserving nulls - const rawValues = activePayload - .filter((item) => item.value !== undefined && dataKeys.includes(item.dataKey as string)) - .map((item) => item.value); + // Use the full data row so the total covers ALL dataKeys, not just visibleSeries + const dataRow = activePayload[0]?.payload; + if (!dataRow) return grandTotal; + + const rawValues = dataKeys.map((key) => dataRow[key]); - // Filter to non-null values only const values = rawValues .filter((v): v is number => v != null) .map((v) => Number(v) || 0); @@ -88,7 +88,6 @@ export function ChartLegendCompound({ if (values.length === 0) return null; if (!aggregation) { - // Default: sum return values.reduce((a, b) => a + b, 0); } return aggregateValues(values, aggregation); @@ -113,24 +112,24 @@ export function ChartLegendCompound({ const currentData = useMemo((): Record => { if (!activePayload?.length) return totals; - // If we have activePayload data from hovering over a bar/line - const hoverData = activePayload.reduce( - (acc, item) => { - if (item.dataKey && item.value !== undefined) { - // Preserve null for gap-filled points instead of coercing to 0 - acc[item.dataKey] = item.value != null ? Number(item.value) || 0 : null; - } - return acc; - }, - {} as Record - ); + // Use the full data row so ALL dataKeys are resolved from the hovered point, + // not just the visibleSeries present in activePayload. + const dataRow = activePayload[0]?.payload; + if (!dataRow) return totals; + + const hoverData: Record = {}; + for (const key of dataKeys) { + const value = dataRow[key]; + if (value !== undefined) { + hoverData[key] = value != null ? Number(value) || 0 : null; + } + } - // Return a merged object - totals for keys not in the hover data return { ...totals, ...hoverData, }; - }, [activePayload, totals]); + }, [activePayload, totals, dataKeys]); // Prepare legend items with capped display const legendItems = useMemo(() => {