From 96b2266a9df401ec3a3e9cb62e20af91ae7f3cb4 Mon Sep 17 00:00:00 2001 From: gorkem-bwl Date: Fri, 28 Aug 2026 10:33:28 -0400 Subject: [PATCH 1/3] fix(infrastructure): wrap gauge row so every disk stays reachable The gauge row on the infrastructure details page laid out memory, CPU and one gauge per disk in a single flex row with no wrapping and no overflow handling. Each gauge is capped at 260px, so on a host with enough disks the row ran past the content column. RootLayout sets overflow: "hidden" on that column, so the excess was clipped outright rather than becoming scrollable - the later disks rendered but could not be reached by any means. Three changes, all scoped to this row: flexWrap moves the overflow onto additional rows. useFlexGap is required alongside it. MUI's Stack implements `spacing` as `& > :not(style) ~ :not(style) { marginLeft }`, and that selector is DOM-order based rather than line-aware, so the first card of each wrapped row would carry a spurious 16px left margin and misalign against the row above. useFlexGap switches to a real flex gap. flexBasis on the children is what actually makes the line break. BaseChart sets `flex: 1`, which expands to `flex: 1 1 0%`; wrapping is decided by the sum of items' hypothetical main sizes, so with a zero basis that sum is 0 and the row never overflows. The cards would instead shrink to min-content (roughly the 70px gauge plus the widest label) and stay on one cramped line. Giving each child a 260px basis makes the row wrap at the intended card width. The basis is applied through the row's own `& > *` selector rather than by changing BaseChart, which has eight other consumers that default to maxWidth: "100%" and would have had their layout altered. The repeated 260 literals are now a named constant. Only affects viewports at or above the md breakpoint; below it the stack is already a column, where flexWrap is inert. Claude-Session: https://claude.ai/code/session_01AbYLvwpEaZFXktHVcqrFRd --- .../Details/Components/Gauges.tsx | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/client/src/Pages/Infrastructure/Details/Components/Gauges.tsx b/client/src/Pages/Infrastructure/Details/Components/Gauges.tsx index e2b053aef..2e9e88a0f 100644 --- a/client/src/Pages/Infrastructure/Details/Components/Gauges.tsx +++ b/client/src/Pages/Infrastructure/Details/Components/Gauges.tsx @@ -8,6 +8,9 @@ import { useTheme } from "@mui/material"; import useMediaQuery from "@mui/material/useMediaQuery"; import type { CheckSnapshot } from "@/Types/Check"; +// Width each gauge card aims for, and the basis the wrapping row breaks on. +const GAUGE_MAX_WIDTH = 260; + export const InfraDetailsGauges = ({ snapshot, }: { @@ -26,10 +29,19 @@ export const InfraDetailsGauges = ({ direction={isSmall ? "column" : "row"} spacing={theme.spacing(8)} alignItems={"stretch"} + flexWrap={"wrap"} + useFlexGap + sx={{ + // The gauge cards are flex: 1 1 0, so a wrapping row would never + // overflow and they would squash to min-content instead of breaking + // the line. Give each one its own width as the basis so the row wraps + // at the intended card size. + "& > *": { flexBasis: GAUGE_MAX_WIDTH }, + }} > Date: Mon, 31 Aug 2026 09:21:35 -0700 Subject: [PATCH 2/3] add a flex basis prop instead of one-off fix --- client/src/Components/design-elements/BaseChart.tsx | 3 +++ client/src/Components/design-elements/Gauge.tsx | 3 +++ .../Pages/Infrastructure/Details/Components/Gauges.tsx | 9 +-------- 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/client/src/Components/design-elements/BaseChart.tsx b/client/src/Components/design-elements/BaseChart.tsx index 46abe5d39..319a4ad51 100644 --- a/client/src/Components/design-elements/BaseChart.tsx +++ b/client/src/Components/design-elements/BaseChart.tsx @@ -12,6 +12,7 @@ type BaseChartProps = React.PropsWithChildren<{ title: string; width?: number | string; maxWidth?: number | string; + flexBasis?: number | string; padding?: number | string | ResponsiveStyleValue; onClick?: () => void; }>; @@ -21,6 +22,7 @@ export const BaseChart = ({ title, width = "100%", maxWidth = "100%", + flexBasis = "0%", padding, onClick, }: BaseChartProps) => { @@ -32,6 +34,7 @@ export const BaseChart = ({ padding: padding ?? theme.spacing(LAYOUT.MD), display: "flex", flex: 1, + flexBasis, width: width, maxWidth: maxWidth, ...(onClick && { diff --git a/client/src/Components/design-elements/Gauge.tsx b/client/src/Components/design-elements/Gauge.tsx index 4130f67a7..082ccd996 100644 --- a/client/src/Components/design-elements/Gauge.tsx +++ b/client/src/Components/design-elements/Gauge.tsx @@ -123,6 +123,7 @@ export const DetailGauge = ({ lowerLabel, lowerValue, maxWidth = 225, + flexBasis = "0%", }: { title: string; progress: number; @@ -131,6 +132,7 @@ export const DetailGauge = ({ lowerLabel?: string; lowerValue?: string | number; maxWidth?: number; + flexBasis?: number | string; }) => { const theme = useTheme(); return ( @@ -138,6 +140,7 @@ export const DetailGauge = ({ icon={null} title={title} maxWidth={maxWidth} + flexBasis={flexBasis} > *": { flexBasis: GAUGE_MAX_WIDTH }, - }} > Date: Mon, 31 Aug 2026 09:24:56 -0700 Subject: [PATCH 3/3] add missing props --- client/src/Pages/Infrastructure/Details/Components/Gauges.tsx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/client/src/Pages/Infrastructure/Details/Components/Gauges.tsx b/client/src/Pages/Infrastructure/Details/Components/Gauges.tsx index e67871983..1b94580fd 100644 --- a/client/src/Pages/Infrastructure/Details/Components/Gauges.tsx +++ b/client/src/Pages/Infrastructure/Details/Components/Gauges.tsx @@ -49,6 +49,7 @@ export const InfraDetailsGauges = ({ upperValue={getFrequency(snapshot?.cpu?.current_frequency || 0)} lowerLabel={t("pages.infrastructure.gauges.cpu.lowerLabel")} lowerValue={getFrequency(snapshot?.cpu?.frequency || 0)} + flexBasis={isSmall ? "auto" : GAUGE_MAX_WIDTH} /> {snapshot?.disk?.map((disk, idx) => { return ( @@ -62,6 +63,7 @@ export const InfraDetailsGauges = ({ upperValue={prettyBytes(disk?.used_bytes || 0)} lowerLabel={t("pages.infrastructure.gauges.disk.lowerLabel")} lowerValue={prettyBytes(disk?.total_bytes || 0)} + flexBasis={isSmall ? "auto" : GAUGE_MAX_WIDTH} /> ); })}