diff --git a/internal/site/src/components/charts/area-chart.tsx b/internal/site/src/components/charts/area-chart.tsx index 183600293..3daf10928 100644 --- a/internal/site/src/components/charts/area-chart.tsx +++ b/internal/site/src/components/charts/area-chart.tsx @@ -6,6 +6,7 @@ import { ChartLegendContent, ChartTooltip, ChartTooltipContent, + fixedDomainTicks, xAxis, } from "@/components/ui/chart" import { chartMargin, cn, formatShortDate } from "@/lib/utils" @@ -143,6 +144,7 @@ export default function AreaChartDefault({ className="tracking-tighter" width={yAxisWidth} domain={domain ?? [0, max ?? "auto"]} + ticks={fixedDomainTicks(domain ?? [0, max ?? "auto"])} tickFormatter={(value, index) => updateYAxisWidth(tickFormatter(value, index))} tickLine={false} axisLine={false} diff --git a/internal/site/src/components/charts/line-chart.tsx b/internal/site/src/components/charts/line-chart.tsx index 211c1f482..d825a7d5b 100644 --- a/internal/site/src/components/charts/line-chart.tsx +++ b/internal/site/src/components/charts/line-chart.tsx @@ -6,6 +6,7 @@ import { ChartLegendContent, ChartTooltip, ChartTooltipContent, + fixedDomainTicks, xAxis, } from "@/components/ui/chart" import { chartMargin, cn, formatShortDate } from "@/lib/utils" @@ -186,6 +187,7 @@ export default function LineChartDefault({ className="tracking-tighter" width={yAxisWidth} domain={domain ?? [0, max ?? "auto"]} + ticks={fixedDomainTicks(domain ?? [0, max ?? "auto"])} tickFormatter={(value, index) => updateYAxisWidth(tickFormatter(value, index))} tickLine={false} axisLine={false} @@ -199,6 +201,7 @@ export default function LineChartDefault({ className="tracking-tighter" width={rightAxisWidth} domain={domain2 ?? [0, max2 ?? "auto"]} + ticks={fixedDomainTicks(domain2 ?? [0, max2 ?? "auto"])} tickFormatter={tickFormatter2 ?? tickFormatter} tickLine={false} axisLine={false} diff --git a/internal/site/src/components/routes/system/charts/cpu-charts.tsx b/internal/site/src/components/routes/system/charts/cpu-charts.tsx index 5045c153a..813dfb6af 100644 --- a/internal/site/src/components/routes/system/charts/cpu-charts.tsx +++ b/internal/site/src/components/routes/system/charts/cpu-charts.tsx @@ -4,7 +4,6 @@ import { useContainerDataPoints } from "@/components/charts/hooks" import { decimalString, toFixedFloat } from "@/lib/utils" import type { ChartConfig } from "@/components/ui/chart" import type { ChartData } from "@/types" -import { pinnedAxisDomain } from "@/components/ui/chart" import CpuCoresSheet from "../cpu-sheet" import { ChartCard, FilterBar, SelectAvgMax } from "../chart-card" import { dockerOrPodman } from "../chart-data" @@ -52,7 +51,6 @@ export function CpuChart({ ]} tickFormatter={(val) => `${toFixedFloat(val, 2)}%`} contentFormatter={({ value }) => `${decimalString(value)}%`} - domain={pinnedAxisDomain()} /> ) @@ -87,7 +85,6 @@ export function ContainerCpuChart({ dataPoints={dataPoints} tickFormatter={(val) => `${toFixedFloat(val, 2)}%`} contentFormatter={({ value }) => `${decimalString(value)}%`} - domain={pinnedAxisDomain()} showTotal={true} reverseStackOrder={true} filter={filter} diff --git a/internal/site/src/components/routes/system/charts/disk-charts.tsx b/internal/site/src/components/routes/system/charts/disk-charts.tsx index 572ce262d..342230321 100644 --- a/internal/site/src/components/routes/system/charts/disk-charts.tsx +++ b/internal/site/src/components/routes/system/charts/disk-charts.tsx @@ -4,7 +4,6 @@ import { decimalString, formatBytes, toFixedFloat } from "@/lib/utils" import type { SystemStatsRecord } from "@/types" import { ChartCard, SelectAvgMax } from "../chart-card" import { Unit } from "@/lib/enums" -import { pinnedAxisDomain } from "@/components/ui/chart" import DiskIoSheet from "../disk-io-sheet" import type { SystemData } from "../use-system-data" import { useStore } from "@nanostores/react" @@ -194,7 +193,6 @@ export function DiskIOChart({ systemData, extraFsName }: { systemData: SystemDat `${toFixedFloat(val, 2)}%`} contentFormatter={({ value }) => `${decimalString(value)}%`} maxToggled={showMax} diff --git a/internal/site/src/components/routes/system/charts/memory-charts.tsx b/internal/site/src/components/routes/system/charts/memory-charts.tsx index a9a969757..efdd35754 100644 --- a/internal/site/src/components/routes/system/charts/memory-charts.tsx +++ b/internal/site/src/components/routes/system/charts/memory-charts.tsx @@ -7,7 +7,6 @@ import type { ChartData, SystemStatsRecord } from "@/types" import { ChartCard, FilterBar, SelectAvgMax } from "../chart-card" import { dockerOrPodman } from "../chart-data" import { decimalString, formatBytes, toFixedFloat } from "@/lib/utils" -import { pinnedAxisDomain } from "@/components/ui/chart" export function MemoryChart({ chartData, @@ -114,7 +113,6 @@ export function ContainerMemoryChart({ const { value, unit } = formatBytes(item.value, false, Unit.Bytes, true) return `${decimalString(value)} ${unit}` }} - domain={pinnedAxisDomain()} showTotal={true} reverseStackOrder={true} filter={filter} diff --git a/internal/site/src/components/routes/system/charts/network-charts.tsx b/internal/site/src/components/routes/system/charts/network-charts.tsx index 047aa72c8..9fd9984fe 100644 --- a/internal/site/src/components/routes/system/charts/network-charts.tsx +++ b/internal/site/src/components/routes/system/charts/network-charts.tsx @@ -5,7 +5,6 @@ import { useContainerDataPoints } from "@/components/charts/hooks" import { $userSettings } from "@/lib/stores" import { decimalString, formatBytes, toFixedFloat } from "@/lib/utils" import type { ChartConfig } from "@/components/ui/chart" -import { pinnedAxisDomain } from "@/components/ui/chart" import type { ChartData, SystemStatsRecord } from "@/types" import { Separator } from "@/components/ui/separator" import NetworkSheet from "../network-sheet" @@ -171,7 +170,6 @@ export function ContainerNetworkChart({ return `${toFixedFloat(value, value >= 10 ? 0 : 1)} ${unit}` }} contentFormatter={contentFormatter} - domain={pinnedAxisDomain()} showTotal={true} reverseStackOrder={true} filter={filter} diff --git a/internal/site/src/components/routes/system/cpu-sheet.tsx b/internal/site/src/components/routes/system/cpu-sheet.tsx index b4fcb0419..080d70009 100644 --- a/internal/site/src/components/routes/system/cpu-sheet.tsx +++ b/internal/site/src/components/routes/system/cpu-sheet.tsx @@ -195,7 +195,7 @@ export default memo(function CpuCoresSheet({ opacity: 0.35, }, ]} - tickFormatter={(val) => `${val}%`} + tickFormatter={(val) => `${toFixedFloat(val, 2)}%`} contentFormatter={({ value }) => `${value}%`} /> diff --git a/internal/site/src/components/routes/system/disk-io-sheet.tsx b/internal/site/src/components/routes/system/disk-io-sheet.tsx index 93acfec8a..7e433c2ee 100644 --- a/internal/site/src/components/routes/system/disk-io-sheet.tsx +++ b/internal/site/src/components/routes/system/disk-io-sheet.tsx @@ -12,7 +12,6 @@ import { decimalString, formatBytes, toFixedFloat } from "@/lib/utils" import { ChartCard, SelectAvgMax } from "@/components/routes/system/chart-card" import type { SystemData } from "@/components/routes/system/use-system-data" import { diskDataFns, DiskUtilizationChart } from "./charts/disk-charts" -import { pinnedAxisDomain } from "@/components/ui/chart" export default memo(function DiskIOSheet({ systemData, @@ -129,7 +128,6 @@ export default memo(function DiskIOSheet({ maxToggled={showMax} chartProps={chartProps} showTotal={true} - domain={pinnedAxisDomain()} itemSorter={(a, b) => a.order - b.order} reverseStackOrder={true} dataPoints={[ @@ -176,7 +174,6 @@ export default memo(function DiskIOSheet({ > `${toFixedFloat(val, 2)}%`} contentFormatter={({ value }) => `${decimalString(value)}%`} maxToggled={showMax} @@ -216,7 +213,6 @@ export default memo(function DiskIOSheet({ > `${toFixedFloat(val, 2)}`} contentFormatter={({ value }) => decimalString(value, value < 10 ? 3 : 2)} maxToggled={showMax} @@ -248,7 +244,6 @@ export default memo(function DiskIOSheet({ > `${toFixedFloat(val, 2)} ms`} contentFormatter={({ value }) => `${decimalString(value)} ms`} maxToggled={showMax} diff --git a/internal/site/src/components/ui/chart.tsx b/internal/site/src/components/ui/chart.tsx index 35c606ce9..8bfe85980 100644 --- a/internal/site/src/components/ui/chart.tsx +++ b/internal/site/src/components/ui/chart.tsx @@ -474,17 +474,19 @@ export { // ChartStyle, } -export function pinnedAxisDomain(): AxisDomain { - return [ - 0, - (dataMax: number) => { - if (dataMax > 10) { - return Math.round(dataMax) - } - if (dataMax > 1) { - return Math.round(dataMax / 0.1) * 0.1 - } - return dataMax - }, - ] +const roundFloat = (value: number) => Number(value.toPrecision(12)) + +/** + * Four equal intervals for a fixed [0, max] domain (e.g. total memory or disk size), with max as the top tick. + * Recharts stops one full step before max, which leaves a large gap below the top tick. + */ +export function fixedDomainTicks(domain?: AxisDomain): number[] | undefined { + if (!Array.isArray(domain)) { + return undefined + } + const [min, max] = domain + if (min !== 0 || typeof max !== "number" || !(max > 0) || !Number.isFinite(max)) { + return undefined + } + return [0, 1, 2, 3, 4].map((i) => roundFloat((max * i) / 4)) }