From 840e12eb9a060fbefb032a5e00d658e2cb4bac82 Mon Sep 17 00:00:00 2001 From: gorkem-bwl Date: Fri, 28 Aug 2026 11:22:29 -0400 Subject: [PATCH] fix(infrastructure): clamp gauge arc and fix disk key fallback Two small pre-existing bugs in the infrastructure gauges. Arc overdraw. Gauge computed strokeLength from the raw `progress` prop while the label and the fill colour both used `progressWithinRange`, the value clamped to 0-100. A reading above 100% therefore swept the arc past a full circle - the offset (circumference - strokeLength) went negative - while the label still read "100.0%". A negative reading drew the arc backwards for the same reason. strokeLength now uses the clamped value, so out-of-range input stops at exactly one turn and matches what the label and colour already showed. Values in range are unaffected. The effect that animates the arc also listed `progress` in its dependency array while only reading `strokeLength`, so it re-ran the 100ms animation on changes that could not alter the arc (105% to 110%, say). Now that strokeLength is derived from the clamped value, the stale dependency is dropped. Disk key fallback. `disk?.device || 0 + idx` parses as `disk?.device || (0 + idx)` because + binds tighter than ||, so the fallback was just `idx` and the leading 0 did nothing. It happened to produce unique keys, but by accident rather than intent, and a disk whose device is the empty string collided with index 0. Replaced with a `disk-${idx}` template so the intent is explicit. Claude-Session: https://claude.ai/code/session_01AbYLvwpEaZFXktHVcqrFRd --- client/src/Components/design-elements/Gauge.tsx | 9 ++++++--- .../Pages/Infrastructure/Details/Components/Gauges.tsx | 2 +- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/client/src/Components/design-elements/Gauge.tsx b/client/src/Components/design-elements/Gauge.tsx index 4130f67a7..d53ce4da5 100644 --- a/client/src/Components/design-elements/Gauge.tsx +++ b/client/src/Components/design-elements/Gauge.tsx @@ -39,9 +39,12 @@ export const Gauge = forwardRef(function Gauge( () => ({ circumference: 2 * Math.PI * radius, totalSize: radius * 2 + strokeWidth * 2, - strokeLength: (progress / 100) * (2 * Math.PI * radius), + // Uses the clamped value, like the label and the fill color: an + // out-of-range reading would otherwise sweep the arc past a full circle + // while the label read 100%. + strokeLength: (progressWithinRange / 100) * (2 * Math.PI * radius), }), - [radius, strokeWidth, progress] + [radius, strokeWidth, progressWithinRange] ); const [offset, setOffset] = useState(circumference); @@ -52,7 +55,7 @@ export const Gauge = forwardRef(function Gauge( }, 100); return () => clearTimeout(timer); - }, [progress, circumference, strokeLength]); + }, [circumference, strokeLength]); const fillColor = getInfraGaugeColor(progressWithinRange, theme); diff --git a/client/src/Pages/Infrastructure/Details/Components/Gauges.tsx b/client/src/Pages/Infrastructure/Details/Components/Gauges.tsx index e2b053aef..75741e6c2 100644 --- a/client/src/Pages/Infrastructure/Details/Components/Gauges.tsx +++ b/client/src/Pages/Infrastructure/Details/Components/Gauges.tsx @@ -48,7 +48,7 @@ export const InfraDetailsGauges = ({ {snapshot?.disk?.map((disk, idx) => { return (