diff --git a/frontend/components/dashboard/scan-terminal/TemperatureTooltipContent.tsx b/frontend/components/dashboard/scan-terminal/TemperatureTooltipContent.tsx index 67ed3b00..c7ac9028 100644 --- a/frontend/components/dashboard/scan-terminal/TemperatureTooltipContent.tsx +++ b/frontend/components/dashboard/scan-terminal/TemperatureTooltipContent.tsx @@ -77,8 +77,8 @@ export function TemperatureTooltipContent({ )} {probabilityRows.length > 0 && ( -
0 ? "mt-1.5 grid gap-1 border-t border-slate-100 pt-1.5" : "grid gap-1"}> - {probabilityRows.slice(0, 8).map((item) => ( +
0 ? "mt-1.5 grid max-h-[260px] gap-1 overflow-y-auto border-t border-slate-100 pt-1.5 pr-1" : "grid max-h-[260px] gap-1 overflow-y-auto pr-1"}> + {probabilityRows.map((item) => (
@@ -118,6 +118,18 @@ function buildTooltipRows( .filter((item): item is TooltipRow => item !== null); } +function formatProbabilityRangeValue(value: number) { + return Number(value.toFixed(1)).toString(); +} + +function formatProbabilityRangeLabel( + lower: number, + upper: number, + tempSymbol: string, +) { + return `${formatProbabilityRangeValue(lower)}-${formatProbabilityRangeValue(upper)}${tempSymbol}`; +} + function buildTooltipProbabilityRows( probabilityOverlay: ProbabilityOverlay | null | undefined, tempSymbol: string, @@ -135,18 +147,20 @@ function buildTooltipProbabilityRows( }); } - const topBand = [...probabilityOverlay.bands] - .filter((band) => validNumber(band.probability) !== null) - .sort((a, b) => b.probability - a.probability)[0]; - if (topBand) { - const probabilityPct = Math.round(topBand.probability * 100); - rows.push({ - key: topBand.key, - label: topBand.label, - value: `${probabilityPct}%`, - color: "#a78bfa", - }); - } + rows.push( + ...[...probabilityOverlay.bands] + .filter((band) => validNumber(band.probability) !== null && band.probability > 0) + .sort((a, b) => a.lower - b.lower) + .map((band) => { + const probabilityPct = Math.round(band.probability * 100); + return { + key: band.key, + label: formatProbabilityRangeLabel(band.lower, band.upper, tempSymbol), + value: `${probabilityPct}%`, + color: "#a78bfa", + }; + }), + ); return rows; } diff --git a/frontend/components/dashboard/scan-terminal/__tests__/temperatureTooltipContent.test.ts b/frontend/components/dashboard/scan-terminal/__tests__/temperatureTooltipContent.test.ts index 8500b8a4..bafcf8af 100644 --- a/frontend/components/dashboard/scan-terminal/__tests__/temperatureTooltipContent.test.ts +++ b/frontend/components/dashboard/scan-terminal/__tests__/temperatureTooltipContent.test.ts @@ -61,6 +61,15 @@ export function runTests() { engine: "legacy", muLine: { value: 27.4, label: "Gaussian μ 27.4°C" }, bands: [ + { + key: "legacy_probability_26_0", + value: 26, + lower: 25.5, + upper: 26.5, + probability: 0.18, + label: "26°C 18%", + opacity: 0.08, + }, { key: "legacy_probability_27_0", value: 27, @@ -70,6 +79,15 @@ export function runTests() { label: "27°C 42%", opacity: 0.13, }, + { + key: "legacy_probability_28_0", + value: 28, + lower: 27.5, + upper: 28.5, + probability: 0.31, + label: "28°C 31%", + opacity: 0.11, + }, ], }, "°C", @@ -77,13 +95,15 @@ export function runTests() { ); assert( - probabilityRows.length === 2, - "temperature tooltip should show Gaussian μ and the leading probability bucket as compact context", + probabilityRows.length === 4, + "temperature tooltip should show Gaussian μ and every available probability bucket as compact context", ); assert( probabilityRows.some((row) => row.key === "legacy_probability_mu" && row.value === "27.4°C") && - probabilityRows.some((row) => row.key === "legacy_probability_27_0" && row.value === "42%"), - "temperature tooltip should format Gaussian μ and probability values without drawing a full probability band on the main chart", + probabilityRows.some((row) => row.key === "legacy_probability_26_0" && row.label === "25.5-26.5°C" && row.value === "18%") && + probabilityRows.some((row) => row.key === "legacy_probability_27_0" && row.label === "26.5-27.5°C" && row.value === "42%") && + probabilityRows.some((row) => row.key === "legacy_probability_28_0" && row.label === "27.5-28.5°C" && row.value === "31%"), + "temperature tooltip should format the full Gaussian probability distribution by temperature range without drawing it on the main chart", ); const projectRoot = process.cwd();