From 3105d5c305469a87326468d113ed9aa05eea6907 Mon Sep 17 00:00:00 2001 From: rcourtman <8825017+rcourtman@users.noreply.github.com> Date: Mon, 5 Oct 2026 16:39:54 +0100 Subject: [PATCH] Keep the Proxmox guest Backup badge whole at laptop widths The guests table's Backup badge does not truncate, but the column was too narrow for it. Running is 73px with its shield and Unknown 79px. The compact layout gave Backup a weight of 5 (a 33-58px content box from 1000 to 1513px) and the wide layout 72px, so Running was cut inside its pill at every width up to 1600px, and None and month ages up to about 1500px. Running is the badge that says a backup is underway. The compact weights now give Backup 10, taken from Type (5.4, still room for the VM/LXC badge and the sorted header) and CPU (9.6, whose bar shows only a percentage and core count). The wide column is 96px, taken from CPU (116px). Name, ID, Uptime, Net I/O, Disk I/O and the memory and disk bars keep their widths and used/total sublabels, and views without a Backup column give them slightly more. Two GuestRow width expectations for the pod and Docker views move with the CPU weight. --- .../subsystems/performance-and-scalability.md | 12 +++ .../0c24a36bf1559a9d.json | 90 +++++++++++++++++++ .../Workloads/__tests__/GuestRow.test.tsx | 4 +- ...loadsSurface.performance.contract.test.tsx | 24 +++++ .../components/Workloads/guestRowModel.tsx | 21 +++-- 5 files changed, 143 insertions(+), 8 deletions(-) create mode 100644 frontend-modern/browser-verification/0c24a36bf1559a9d.json diff --git a/docs/release-control/v6/internal/subsystems/performance-and-scalability.md b/docs/release-control/v6/internal/subsystems/performance-and-scalability.md index 8610516f3c..d2e5c393d5 100644 --- a/docs/release-control/v6/internal/subsystems/performance-and-scalability.md +++ b/docs/release-control/v6/internal/subsystems/performance-and-scalability.md @@ -3757,6 +3757,18 @@ returns focus to the originating disclosure. Nested evidence activation must not trigger the enclosing guest row. Touch targets are at least 44px; compact desktop shields and the existing status colours remain. +The Backup column badge does not truncate. Running (73px with its shield) and +Unknown (79px) need about 95px with cell padding, so the compact layout weights +give Backup 10 against Type 5.4 and CPU 9.6, and the wide column is 96px with +the extra 24px taken from CPU (116px). Type still fits its VM/LXC badge and +sorted header, and CPU its percentage and core count, while Name, ID, Uptime, +Net I/O, Disk I/O and the memory and disk bars keep their widths and used/total +sublabels; views without a Backup column (pods, Docker) give them slightly more. +Before this, Running was cut inside its pill at every width up to 1600px, and +None and month ages up to about 1500px. +`WorkloadsSurface.performance.contract.test.tsx` checks the narrowest compact +table and the wide width. + The evidence content is reactive to the same guest identity: running is not completion, malformed/future times are unknown, and only the existing absence sentinels mean no backup recorded. A removed row unmounts its disclosure and diff --git a/frontend-modern/browser-verification/0c24a36bf1559a9d.json b/frontend-modern/browser-verification/0c24a36bf1559a9d.json new file mode 100644 index 0000000000..74bf4631f9 --- /dev/null +++ b/frontend-modern/browser-verification/0c24a36bf1559a9d.json @@ -0,0 +1,90 @@ +{ + "version": 1, + "base_sha": "ebd6d09337d5e4cd17b327df5a69a58dae739a27", + "verified_at": "2026-10-05T15:39:31Z", + "result": "passed", + "changed_paths": [ + "frontend-modern/src/components/Workloads/guestRowModel.tsx" + ], + "content_sha256": { + "frontend-modern/src/components/Workloads/guestRowModel.tsx": "fa970cac1cde21056bc707a5ec6dc056d9f4dc9362f83a5bf8b59d5c2af1f75f" + }, + "routes": [ + "/proxmox/overview", + "/vmware/overview" + ], + "viewports": [ + { + "width": 390, + "height": 900 + }, + { + "width": 600, + "height": 900 + }, + { + "width": 768, + "height": 900 + }, + { + "width": 900, + "height": 900 + }, + { + "width": 973, + "height": 900 + }, + { + "width": 1000, + "height": 900 + }, + { + "width": 1024, + "height": 900 + }, + { + "width": 1100, + "height": 900 + }, + { + "width": 1180, + "height": 900 + }, + { + "width": 1280, + "height": 900 + }, + { + "width": 1366, + "height": 900 + }, + { + "width": 1440, + "height": 900 + }, + { + "width": 1513, + "height": 900 + }, + { + "width": 1600, + "height": 900 + }, + { + "width": 1920, + "height": 900 + } + ], + "states": [ + "Private mock stack (PULSE_MOCK_MODE, random metrics off) serving this tree on main ebd6d09337; before = main, after = main plus this change, measured in the same session", + "Backup badge fit (each label cloned at natural width into the narrowest Backup cell): Running 73px, Unknown 79px, None 58px, 12mo 61px, 21d 52px with the shield. On main the column content box was 33-65px from 1000 to 1600 (compact layout weight 5, wide 72px), so Running and Unknown clipped at every width up to 1600 and None and month ages up to 1440-1513; patched the content box is 81-132px and every label fits at every width where the column shows (1000 to 1920)", + "Clip sweep over every cell of the Workloads table and its overflow-hidden or ellipsis descendants, .sr-only excluded, 15 widths 390 to 1920: Proxmox 464 to 452 and vSphere 2 to 1 clipped elements, no column clips more at any width, and the memory and disk used/total sublabels and the CPU core counts are unchanged in every row", + "Column widths patched at 1024: Name 259, Type 54, ID 70, CPU 96, Mem 140, Disk 140, Uptime 80, Backup 100 (main 259/70/70/130/140/140/80/50); at 1600 (wide) Name 224, CPU 130, Backup 108, Net I/O and Disk I/O 191 (main 224/157/81/191)", + "Before and after element screenshots of the guest table around the Running row at 1024, 1280 and 1600: Running cut inside its pill on main, whole patched" + ], + "interactions": [ + "Loaded each route fresh, waited for the row count to settle, resized through every viewport before measuring", + "Clicked the Running backup badge at 1024, 1280 and 1600: the Backup status evidence dialog opened (Backup running now\u2026) and Escape closed it", + "Clicked a guest row's name cell to open its details on both routes; no console errors" + ] +} diff --git a/frontend-modern/src/components/Workloads/__tests__/GuestRow.test.tsx b/frontend-modern/src/components/Workloads/__tests__/GuestRow.test.tsx index 079934ef2c..672d3aa14b 100644 --- a/frontend-modern/src/components/Workloads/__tests__/GuestRow.test.tsx +++ b/frontend-modern/src/components/Workloads/__tests__/GuestRow.test.tsx @@ -1788,7 +1788,7 @@ describe('GUEST_COLUMNS', () => { 'aiContext', ]); expect(getGuestColumnWidthStyle('name', false, 'compact', compactPodColumnIds)).toEqual({ - width: '25%', + width: '25.8449%', }); }); @@ -1807,7 +1807,7 @@ describe('GUEST_COLUMNS', () => { expect( getGuestColumnWidthStyle('update', false, 'compact', compactDockerRuntimeColumnIds), ).toEqual({ - width: '8.9286%', + width: '9.2081%', }); }); diff --git a/frontend-modern/src/components/Workloads/__tests__/WorkloadsSurface.performance.contract.test.tsx b/frontend-modern/src/components/Workloads/__tests__/WorkloadsSurface.performance.contract.test.tsx index 4217231ea1..d2aa75fff9 100644 --- a/frontend-modern/src/components/Workloads/__tests__/WorkloadsSurface.performance.contract.test.tsx +++ b/frontend-modern/src/components/Workloads/__tests__/WorkloadsSurface.performance.contract.test.tsx @@ -5,6 +5,7 @@ import { Route, Router } from '@solidjs/router'; import type { Resource } from '@/types/resource'; import { syncSessionSettingsCapabilities } from '@/stores/sessionSettingsCapabilities'; import { WorkloadsSurface } from '../WorkloadsSurface'; +import { WORKLOAD_TABLE_CONTAINER_TABLET_WIDTH, getGuestColumnStyle } from '../guestRowModel'; import workloadsSource from '../WorkloadsSurface.tsx?raw'; import workloadsFilterSource from '../WorkloadsFilter.tsx?raw'; import workloadsWorkloadTableSource from '../WorkloadsTable.tsx?raw'; @@ -1870,3 +1871,26 @@ describe('Workloads performance contract', () => { }); }); }); + +describe('Workloads Backup column fit', () => { + // The backup badge does not truncate: Running is 73px and Unknown 79px with + // the shield, plus 8px of cell padding a side. The compact layout starts at a + // 900px table, where the Proxmox guest columns all show. + const badgeWidth = 79 + 16; + + it('keeps the widest backup badge whole at the narrowest compact table', () => { + const proxmoxColumns = ['name', 'type', 'vmid', 'cpu', 'memory', 'disk', 'uptime', 'backup']; + const percent = Number.parseFloat( + String(getGuestColumnStyle('backup', false, 'compact', proxmoxColumns)?.width), + ); + expect((percent / 100) * WORKLOAD_TABLE_CONTAINER_TABLET_WIDTH).toBeGreaterThanOrEqual( + badgeWidth, + ); + }); + + it('keeps the widest backup badge whole in the wide layout', () => { + expect( + Number.parseFloat(String(getGuestColumnStyle('backup', false, 'wide')?.width)), + ).toBeGreaterThanOrEqual(badgeWidth); + }); +}); diff --git a/frontend-modern/src/components/Workloads/guestRowModel.tsx b/frontend-modern/src/components/Workloads/guestRowModel.tsx index 0c7c67ea17..df232cfa02 100644 --- a/frontend-modern/src/components/Workloads/guestRowModel.tsx +++ b/frontend-modern/src/components/Workloads/guestRowModel.tsx @@ -241,7 +241,7 @@ export const GUEST_COLUMNS: ColumnDef[] = [ createVisibleCanonicalTypeColumn(), { id: 'info', label: 'Info', width: '100px', sortKey: 'info', kind: 'numeric-value' }, { id: 'vmid', label: 'ID', width: '45px', sortKey: 'vmid', kind: 'numeric-value' }, - { id: 'cpu', label: 'CPU', width: '140px', sortKey: 'cpu', kind: 'metric-bar' }, + { id: 'cpu', label: 'CPU', width: '116px', sortKey: 'cpu', kind: 'metric-bar' }, { id: 'memory', label: 'Mem', width: '140px', sortKey: 'memory', kind: 'metric-bar' }, { id: 'disk', @@ -411,8 +411,12 @@ export const GUEST_COLUMNS: ColumnDef[] = [ /> ), - width: '72px', - minWidth: '68px', + // The badge does not truncate: Running is 73px and Unknown 79px with the + // shield, so the wide column keeps room for both with cell padding. Its + // extra 24px comes from CPU, whose bar shows only a percentage and core + // count, so the other wide columns keep their widths. + width: '96px', + minWidth: '90px', toggleable: true, kind: 'badge', }, @@ -519,17 +523,22 @@ const GUEST_COLUMN_RESPONSIVE_WEIGHTS: Record< memory: 17, disk: 17, }, + // The Backup badge needs about 95px with cell padding for Unknown (79px) + // and Running (73px) at the narrowest compact table. Its room comes from Type, whose VM/LXC + // badge and sorted header need about 51px, and from CPU, whose bar shows + // only a percentage and core count; Name, ID, Uptime and the memory and + // disk bars keep their widths, so their used/total sublabels stay. compact: { name: 26, runtime: 10, - type: 7, + type: 5.4, info: 7, vmid: 7, - cpu: 13, + cpu: 9.6, memory: 14, disk: 14, uptime: 8, - backup: 5, + backup: 10, image: 18, namespace: 11, context: 13,