From dc5f38287552324f9a0f7e55b80d264435f110ba Mon Sep 17 00:00:00 2001 From: Thomas Date: Wed, 7 Oct 2026 15:39:44 +0200 Subject: [PATCH] fix: avoid stretching Beszel charts while rows overflow (#7074) --- .../src/beszel-system-stats/component.tsx | 6 ++- packages/widgets/src/beszel/_shared/chart.tsx | 2 +- .../widgets/src/beszel/_shared/stats-view.tsx | 38 +++++++------------ 3 files changed, 20 insertions(+), 26 deletions(-) diff --git a/packages/widgets/src/beszel-system-stats/component.tsx b/packages/widgets/src/beszel-system-stats/component.tsx index 588afa92d..bfc19fedf 100644 --- a/packages/widgets/src/beszel-system-stats/component.tsx +++ b/packages/widgets/src/beszel-system-stats/component.tsx @@ -2,6 +2,7 @@ import { useCallback, useMemo, useRef } from "react"; import { ActionIcon, Box, Button, Center, Group, Menu, ScrollArea, Select, Stack, Text } from "@mantine/core"; +import { useElementSize } from "@mantine/hooks"; import { IconAdjustments, IconCheck, IconQuestionMark, IconServer, IconServerOff } from "@tabler/icons-react"; import { getQueryKey } from "@trpc/react-query"; @@ -37,6 +38,7 @@ export default function BeszelSystemStatsWidget({ setOptions, widgetRuntimeRef, }: WidgetComponentProps<"beszelSystemStats">) { + const { ref: viewportRef, height: viewportHeight } = useElementSize(); const t = useI18n("widget.beszelSystemStats"); const tBeszel = useI18n("widget.beszel"); const board = useOptionalBoard(); @@ -298,6 +300,8 @@ export default function BeszelSystemStatsWidget({ )} @@ -308,7 +312,7 @@ export default function BeszelSystemStatsWidget({ systemId={selectedSystem?.systemId ?? ""} timePeriod={options.timePeriod as BeszelTimePeriod} columns={responsiveWidth > 600 ? 2 : 1} - availableHeight={height} + availableHeight={Math.floor(viewportHeight || height)} visibility={{ cpu: options.showCpu, memory: options.showMemory, diff --git a/packages/widgets/src/beszel/_shared/chart.tsx b/packages/widgets/src/beszel/_shared/chart.tsx index e461371a6..2f37a8855 100644 --- a/packages/widgets/src/beszel/_shared/chart.tsx +++ b/packages/widgets/src/beszel/_shared/chart.tsx @@ -92,7 +92,7 @@ const yAxisBase = { tickMargin: 0, tick: { fontSize: "var(--mantine-font-size-xs)" }, } as const; -const chartStyle = { minWidth: 0, minHeight: 1 } as const; +const chartStyle = { minWidth: 0, minHeight: 1, flexGrow: 1, flexShrink: 0 } as const; const panelStyle = { minWidth: 0 } as const; const chartMargin = { top: 0, right: 0, bottom: 0, left: 0 } as const; export const CPU_Y_AXIS_DOMAIN: [number, string] = [0, "auto"]; diff --git a/packages/widgets/src/beszel/_shared/stats-view.tsx b/packages/widgets/src/beszel/_shared/stats-view.tsx index b29207f7c..1c761e808 100644 --- a/packages/widgets/src/beszel/_shared/stats-view.tsx +++ b/packages/widgets/src/beszel/_shared/stats-view.tsx @@ -62,16 +62,6 @@ interface BeszelStatsViewProps { onSwitchToHistorical?: () => void; } -const MIN_CHART_HEIGHT = 64; -const PANEL_ROW_OVERHEAD = 25; -const GRID_ROW_GAP = 16; - -const computeChartHeight = (availableHeight: number | undefined, rowCount: number) => { - if (availableHeight === undefined || rowCount <= 0) return CHART_HEIGHT; - const perRow = (availableHeight - (rowCount - 1) * GRID_ROW_GAP) / rowCount - PANEL_ROW_OVERHEAD; - return Math.max(MIN_CHART_HEIGHT, Math.floor(perRow)); -}; - const whenVisible = (visible: boolean, data: T | undefined) => (visible ? data : undefined); export function BeszelStatsView({ @@ -334,17 +324,17 @@ export function BeszelStatsView({ (visibility.dockerNetwork && dockerNetworkData.length > 0 ? 1 : 0) : 0); const effectiveColumns = Math.min(columns, Math.max(1, renderedPanelCount)) as 1 | 2; - const rowCount = Math.ceil(renderedPanelCount / effectiveColumns); - const chartHeight = computeChartHeight(availableHeight, rowCount); + // Keep each chart at its readable height until every row fits; then share the remaining space. + // This height is already in layout pixels, so avoid Mantine's rem-based scale compensation. return ( - + {visibility.cpu && cpuData.length > 0 && (