mirror of
https://github.com/rcourtman/Pulse.git
synced 2026-10-24 04:33:17 +00:00
Keep the Docker image update badge readable at tablet widths
The Images table's Update check badge needs about 122px with its cell
padding for its longest labels ("Update available", "Managed by
Pulse"). Between the phone projection and the md breakpoint every
non-name column took an equal 17.5 percent share, which left the
column 100px at a 600px viewport, and the 16 percent md width left it
111px at 768px. The badge was cut at the cell edge with a stray
ellipsis dot, and the "UPDATE CHECK" header clipped at 600px.
The table now declares tablet-band widths through the sortable
header's bandWidth (Update check 23, Size 12; Host and Used by keep
their 17.5) and moves 3 points of md width to Update check, one each
from Host, Used by and Size. The longest size values ("1023 MB",
"9.99 GB") still fit both narrower Size columns.
A clip sweep on a mock stack from 390 to 1440px (15 widths) found the
update badge clipped at 600, 640, 700 and 768px before and nowhere
after. A probe of all six labels against the narrowest Update check
cell found none clipping at any width, and no other column clipped
more often than before. The base already carries the Used by
block-truncate span from #2514, so Used by was measured as it now
renders.
This commit is contained in:
@@ -2314,6 +2314,10 @@ not a replacement status card, CTA band, or page-local nested card.
|
||||
`platformTableBandWidthStyle` or the sortable header's `bandWidth`, which
|
||||
sets `--platform-table-band-width`; the shell applies it only inside the band,
|
||||
after the name anchor, so md widths and phone widths are unchanged.
|
||||
A column whose content must read in full (a status badge) is sized for its
|
||||
widest label at the narrowest table in each range: a 34rem container for the
|
||||
band, and the table a 768px viewport leaves (about 695px) for md widths. The
|
||||
Docker Images Update check column needs 23 percent and 19 percent for that.
|
||||
Below a 360-pixel content width, the shared narrow layout promotes identity to
|
||||
40 percent and may remove one additional lowest-priority context column via
|
||||
`platform-table-narrow-hidden` rather than shrinking names and metric values
|
||||
|
||||
@@ -882,7 +882,12 @@ failed and server-denied observations alongside a no-invented-grant control.
|
||||
The Docker phone container projection keeps identity, state when applicable,
|
||||
CPU, memory and update; restart counts remain in the existing detail expansion
|
||||
and return at mobile width. Images retain image, size and update verdict on
|
||||
phones; host and consumers stay reachable in detail. Hidden header/body columns
|
||||
phones; host and consumers stay reachable in detail. The update verdict reads
|
||||
in full at every width: the Update check column keeps the ~122px its longest
|
||||
badge ("Update available", "Managed by Pulse") needs with cell padding, through
|
||||
a 23 percent tablet-band width taken from Size and a 19 percent md width taken
|
||||
from Host, Used by and Size. An equal band share and the old 16 percent md width cut
|
||||
the badge off between 600 and 800px. Hidden header/body columns
|
||||
are symmetric. Swarm rollout tokens render as words with raw state retained in
|
||||
the title; task starts use the shared relative-time primitive with their exact
|
||||
timestamp retained. Native table/model/guardrail tests and the production
|
||||
|
||||
@@ -0,0 +1,99 @@
|
||||
{
|
||||
"version": 1,
|
||||
"base_sha": "8e68bab55a68d80c7fa234a89216daa5e3af8f29",
|
||||
"verified_at": "2026-10-05T13:41:29Z",
|
||||
"result": "passed",
|
||||
"changed_paths": [
|
||||
"frontend-modern/src/features/docker/DockerImagesTable.tsx"
|
||||
],
|
||||
"content_sha256": {
|
||||
"frontend-modern/src/features/docker/DockerImagesTable.tsx": "a4b95eaae2c0b67cc8195b3b5f5812cee3499bd583da195f809bf8ff1c4e81f0"
|
||||
},
|
||||
"routes": [
|
||||
"/docker/images"
|
||||
],
|
||||
"viewports": [
|
||||
{
|
||||
"width": 390,
|
||||
"height": 900
|
||||
},
|
||||
{
|
||||
"width": 430,
|
||||
"height": 900
|
||||
},
|
||||
{
|
||||
"width": 480,
|
||||
"height": 900
|
||||
},
|
||||
{
|
||||
"width": 540,
|
||||
"height": 900
|
||||
},
|
||||
{
|
||||
"width": 573,
|
||||
"height": 900
|
||||
},
|
||||
{
|
||||
"width": 600,
|
||||
"height": 900
|
||||
},
|
||||
{
|
||||
"width": 640,
|
||||
"height": 900
|
||||
},
|
||||
{
|
||||
"width": 700,
|
||||
"height": 900
|
||||
},
|
||||
{
|
||||
"width": 740,
|
||||
"height": 900
|
||||
},
|
||||
{
|
||||
"width": 767,
|
||||
"height": 900
|
||||
},
|
||||
{
|
||||
"width": 768,
|
||||
"height": 900
|
||||
},
|
||||
{
|
||||
"width": 800,
|
||||
"height": 900
|
||||
},
|
||||
{
|
||||
"width": 900,
|
||||
"height": 900
|
||||
},
|
||||
{
|
||||
"width": 1024,
|
||||
"height": 900
|
||||
},
|
||||
{
|
||||
"width": 1100,
|
||||
"height": 900
|
||||
},
|
||||
{
|
||||
"width": 1280,
|
||||
"height": 900
|
||||
},
|
||||
{
|
||||
"width": 1440,
|
||||
"height": 900
|
||||
}
|
||||
],
|
||||
"states": [
|
||||
"Private mock stack (PULSE_MOCK_MODE, random metrics off) serving this tree on main 8e68bab55a, which already carries the Used by block-truncate span from #2514; before = main, after = main plus this change",
|
||||
"Clip sweep (scrollWidth over clientWidth + 1 on every td and its overflow-hidden or ellipsis descendants, .sr-only excluded) at 15 widths from 390 to 1440: the Update check badge clipped at 600, 640, 700 and 768 on main and nowhere patched; total clipped elements 65 on main, 61 patched; Image, Host, Used by and Size clip counts identical at every width (Used by 1/2/2/1 at 600/640/700/740 both ways, 0 from 768)",
|
||||
"Label probe: each of the six update labels (Update available 97.9px, Managed by Pulse 105.8px, Check failed, Not checked, Current, Pinned) cloned into the narrowest Update check cell: on main Update available and Managed by Pulse overflow at 600, 640, 700 and 768, and Managed by Pulse alone at 740 and 800; patched every label fits at every width (Update check content box 113px at the 573px band edge, 116px at 768, 108px at 390)",
|
||||
"Column widths patched: band at 600 Image 171 / Host 100 / Used by 100 / Size 69 / Update check 131 (Host and Used by unchanged from main); md at 768 Image 209 / Host 118 / Used by 160 / Size 76 / Update check 132 (main 209 / 125 / 167 / 83 / 111)",
|
||||
"Size probe: the widest byte strings (1023 MB, 9.99 GB, 99.9 MB, 1023 KB) fit the narrower Size cell at 573, 640, 767, 768, 800 and 900 (worst 49.6px in a 53 to 74px content box)",
|
||||
"The UPDATE CHECK header clipped at 600 on main, including with a sort indicator; patched no header clips at any width, sorted or not",
|
||||
"Before and after element screenshots of the table at 600, 700, 768 and 1440 show the postgres:16.4 Update available badge cut at the cell edge with a stray ellipsis dot on main and whole patched; the phone projection at 390 keeps Image, Size and Update check unchanged"
|
||||
],
|
||||
"interactions": [
|
||||
"Loaded /docker/images fresh, waited for the row count to settle, then resized through every viewport before measuring",
|
||||
"Sorted by Size and by Update check at the 573px band edge and re-measured header clipping",
|
||||
"Expanded and collapsed the Update available row's detail at 390, 600, 768 and 1440 (aria-expanded true then false, detail row visible); no console errors"
|
||||
]
|
||||
}
|
||||
@@ -140,11 +140,21 @@ export const DockerImagesTable: Component<
|
||||
tableClass="min-w-full table-fixed text-xs md:min-w-[880px]"
|
||||
header={
|
||||
<>
|
||||
{/*
|
||||
The Update check badge needs about 122px with its cell
|
||||
padding ("Update available", "Managed by Pulse"). An
|
||||
equal tablet-band share gave it 100px at 600px, and 16%
|
||||
at md gave it 111px at 768px, so the label was cut off.
|
||||
Size values are short, so the band takes the extra room
|
||||
from Size, and md takes a point each from Host, Used by
|
||||
and Size, which had room to spare there.
|
||||
*/}
|
||||
<PlatformSortableTableHead
|
||||
kind="name"
|
||||
sort={sort}
|
||||
sortKey="image"
|
||||
class="platform-table-mobile-w-30 md:w-[30%]"
|
||||
bandWidth={30}
|
||||
>
|
||||
Image
|
||||
</PlatformSortableTableHead>
|
||||
@@ -152,7 +162,8 @@ export const DockerImagesTable: Component<
|
||||
kind="text"
|
||||
sort={sort}
|
||||
sortKey="host"
|
||||
class="platform-table-phone-hidden md:w-[18%]"
|
||||
class="platform-table-phone-hidden md:w-[17%]"
|
||||
bandWidth={17.5}
|
||||
>
|
||||
Host
|
||||
</PlatformSortableTableHead>
|
||||
@@ -160,7 +171,8 @@ export const DockerImagesTable: Component<
|
||||
kind="text"
|
||||
sort={sort}
|
||||
sortKey="usedBy"
|
||||
class="platform-table-phone-hidden md:w-[24%]"
|
||||
class="platform-table-phone-hidden md:w-[23%]"
|
||||
bandWidth={17.5}
|
||||
>
|
||||
Used by
|
||||
</PlatformSortableTableHead>
|
||||
@@ -168,7 +180,8 @@ export const DockerImagesTable: Component<
|
||||
kind="numeric-value"
|
||||
sort={sort}
|
||||
sortKey="size"
|
||||
class="platform-table-mobile-w-20 md:w-[12%]"
|
||||
class="platform-table-mobile-w-20 md:w-[11%]"
|
||||
bandWidth={12}
|
||||
>
|
||||
Size
|
||||
</PlatformSortableTableHead>
|
||||
@@ -176,7 +189,8 @@ export const DockerImagesTable: Component<
|
||||
kind="badge"
|
||||
sort={sort}
|
||||
sortKey="update"
|
||||
class="platform-table-mobile-w-25 md:w-[16%]"
|
||||
class="platform-table-mobile-w-25 md:w-[19%]"
|
||||
bandWidth={23}
|
||||
>
|
||||
<PlatformResponsiveTableLabel compact="Update" full="Update check" />
|
||||
</PlatformSortableTableHead>
|
||||
|
||||
+11
-5
@@ -322,18 +322,24 @@ describe('platform overview layout guardrails', () => {
|
||||
expect(source).toContain('platform-table-mobile-w-30');
|
||||
}
|
||||
// The images phone row keeps image, size and the update verdict; host and
|
||||
// consumers move to the row expansion so the verdict is not clipped.
|
||||
// consumers move to the row expansion so the verdict is not clipped. In
|
||||
// the tablet band and at md the Update check column keeps the ~122px its
|
||||
// longest badge needs ("Update available", "Managed by Pulse"), taken
|
||||
// from Size in the band and from Host, Used by and Size at md.
|
||||
expect(dockerImagesTableSource).toMatch(
|
||||
/sortKey="size"[\s\S]{0,120}?class="platform-table-mobile-w-20 md:w-\[12%\]"/,
|
||||
/sortKey="image"[\s\S]{0,120}?class="platform-table-mobile-w-30 md:w-\[30%\]"\s*bandWidth=\{30\}/,
|
||||
);
|
||||
expect(dockerImagesTableSource).toMatch(
|
||||
/sortKey="host"[\s\S]{0,120}?class="platform-table-phone-hidden md:w-\[18%\]"/,
|
||||
/sortKey="size"[\s\S]{0,120}?class="platform-table-mobile-w-20 md:w-\[11%\]"\s*bandWidth=\{12\}/,
|
||||
);
|
||||
expect(dockerImagesTableSource).toMatch(
|
||||
/sortKey="usedBy"[\s\S]{0,120}?class="platform-table-phone-hidden md:w-\[24%\]"/,
|
||||
/sortKey="host"[\s\S]{0,120}?class="platform-table-phone-hidden md:w-\[17%\]"\s*bandWidth=\{17\.5\}/,
|
||||
);
|
||||
expect(dockerImagesTableSource).toMatch(
|
||||
/sortKey="update"[\s\S]{0,120}?class="platform-table-mobile-w-25 md:w-\[16%\]"/,
|
||||
/sortKey="usedBy"[\s\S]{0,120}?class="platform-table-phone-hidden md:w-\[23%\]"\s*bandWidth=\{17\.5\}/,
|
||||
);
|
||||
expect(dockerImagesTableSource).toMatch(
|
||||
/sortKey="update"[\s\S]{0,120}?class="platform-table-mobile-w-25 md:w-\[19%\]"\s*bandWidth=\{23\}/,
|
||||
);
|
||||
expect(dockerServicesTableSource).toMatch(
|
||||
/sortKey="mode"[\s\S]{0,120}?class="platform-table-phone-hidden md:w-\[8%\]"/,
|
||||
|
||||
Reference in New Issue
Block a user