From c36f11ad329ddb2a5b56e145d3e88b21ab9eefe7 Mon Sep 17 00:00:00 2001 From: OpenSquared Date: Fri, 26 Jun 2026 22:24:31 +0200 Subject: [PATCH] =?UTF-8?q?fix:=20VIX=20slider=20bar=20overflow=20?= =?UTF-8?q?=E2=80=94=20clamp=20pivot=20to=20range,=20add=20center=20prop?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Slider was computing mid = (0 - 10) / (60 - 10) * 100 = -20% for VIX (0 outside the 10-60 range), causing the colored track to start at a negative left position and overflow the container. Fix: add overflow-hidden on the track div; add center prop (defaults 0) that the caller sets to the actual baseline value when 0 is out of range. VIX now pivots at 18, real yield US at 2.1. Co-Authored-By: Claude Sonnet 4.6 --- frontend/src/pages/EuroSimulator.tsx | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/frontend/src/pages/EuroSimulator.tsx b/frontend/src/pages/EuroSimulator.tsx index e21ef02..a7a68ba 100644 --- a/frontend/src/pages/EuroSimulator.tsx +++ b/frontend/src/pages/EuroSimulator.tsx @@ -130,21 +130,25 @@ function compute(p: Params): ModelResult { function Slider({ label, value, min, max, step, format, onChange, - colorize = false, reverse = false, + colorize = false, reverse = false, center, }: { label: string; value: number; min: number; max: number; step: number format: (v: number) => string onChange: (v: number) => void colorize?: boolean reverse?: boolean // true = value goes up → negative (red) + center?: number // neutral pivot point (defaults to 0; use baseline value if 0 is out of range) }) { const pct = ((value - min) / (max - min)) * 100 - const mid = ((0 - min) / (max - min)) * 100 + const pivot = center ?? 0 + // Clamp mid to [0,100] so the track never overflows the container + const mid = Math.max(0, Math.min(100, ((pivot - min) / (max - min)) * 100)) + const atCenter = Math.abs(value - pivot) < step / 2 let trackColor = 'bg-blue-500' if (colorize) { - const isPositive = reverse ? value < 0 : value > 0 - trackColor = value === 0 ? 'bg-slate-600' : isPositive ? 'bg-emerald-500' : 'bg-rose-500' + const isPositive = reverse ? value < pivot : value > pivot + trackColor = atCenter ? 'bg-slate-600' : isPositive ? 'bg-emerald-500' : 'bg-rose-500' } return ( @@ -153,12 +157,12 @@ function Slider({ {label} 0) ? 'text-emerald-400' : 'text-rose-400' + colorize && !atCenter + ? (reverse ? value < pivot : value > pivot) ? 'text-emerald-400' : 'text-rose-400' : 'text-white', )}>{format(value)} -
+
v.toFixed(1)} onChange={v => set('vix', v)} - colorize reverse /> + colorize reverse center={BASE.vix} /> `$${v.toFixed(0)}`} onChange={v => set('oil', v)} /> `${v > 0 ? '+' : ''}${v.toFixed(2)}%`} - onChange={v => set('real_yield_us', v)} colorize reverse /> + onChange={v => set('real_yield_us', v)} colorize reverse center={BASE.real_yield_us} />