mirror of
https://github.com/rcourtman/Pulse.git
synced 2026-10-26 21:47:20 +00:00
Give Alert History messages room to wrap instead of truncating
Alerts > History is where an operator looks back at what happened, and its
table hid the answer. At a 1024px window the card is 600px wide and the Message
column got about 110px, so rows read "Docker servi…" and "Last reading…". Three
action buttons stacked on three lines made every row 75-105px tall, while
Duration, Status and Actions held wide, mostly empty tracks. The row has no
disclosure of its own, so the only way to read the message was to hover.
- Resource and Message now wrap inside a line-clamp-2 wrapper below an 80rem
card (the wrapper sets whitespace-normal itself, because .table-fixed td
forces nowrap) and return to a one-line clamp from 80rem, where the message
track is wide enough and the old 39px row is kept.
- The four density blocks are re-derived from measured natural widths
("08:27 AM" in a 14px monospace, the Resource/Severity/Duration headers, a
119px "acknowledged" badge, three one-line actions at 177px, Type and Node)
at the narrowest card each density serves. The time column is headed "Time",
as on the phone card, because "Timestamp" needed 93px.
- Message keeps a two-line minimum height. The windowing hook sizes its
spacers from one measured row; scrolling a 600-row history in 60px wheel
steps moved a tracked row exactly the scroll distance with uniform 49px rows
and showed 46 jumps up to 20px once rows were 39px and 49px.
Measured in a real browser against an unpatched build of the same tree, at nine
windows from 1024px to 2000px with a 12-hour locale: messages ending in an
ellipsis fell from 82 of 88 rows to 24 of 90 at 1024px, 54 to 17 at 1280px, 24
to 8 at 1440px and 32 to 4 at 1700px; the median row fell from 75px to 49px
from 1280px to 1700px; no time cell or header ended in an ellipsis at any
width. The phone card list is untouched, and Timeline and Resource open and
close as before. Cards under 600px stay cramped; a container-driven switch to
the card list is the remaining fix.
Proofs: the row test pins the wrapper classes, Alerts.helpers pins the header
and class constants, App.architecture asserts the pixel minimums per density,
the 18% Message floor and that each block sits inside its 50rem, 64rem or
80rem container query. Putting the base row markup, header, widths or 50rem
switch point back fails the matching proof.
This commit is contained in:
@@ -1506,13 +1506,42 @@ Info option whose count and filtered rows use the same predicate as every
|
||||
other severity.
|
||||
|
||||
The desktop alert history table sizes each column for its content instead of
|
||||
giving all visible columns an equal share. Timestamp, severity, duration,
|
||||
status, type and node get what their content needs (status fits
|
||||
"acknowledged"), Resource and Node keep at least their old share, the two row
|
||||
actions stay within two lines (one line from an 80rem card), and Message, the
|
||||
column that says what happened, takes the rest. Equal shares held Message to
|
||||
the same 100-160px as the timestamp, so at most a fifth of messages read in
|
||||
full at any width; from a 960px viewport a third to four fifths now do.
|
||||
giving all visible columns an equal share. Each density is sized for the
|
||||
narrowest card it serves (600px, 800px, 1024px and 1280px): Time (the column
|
||||
header; the cell is the row's clock time, `08:27 AM` in a 12-hour locale),
|
||||
severity, duration, status ("acknowledged" needs 119px with its cell padding),
|
||||
the Resource header, the type badge and node (from 1024px) and the three row
|
||||
actions on one line (177px) get the pixels their content and header need at
|
||||
that width, and Message, the column that says what happened, takes the rest
|
||||
and never falls under 18% of the card; `App.architecture.test.ts` holds those
|
||||
minimums and the 50rem, 64rem and 80rem switch points. From an 800px card the
|
||||
three actions share one line; below it they stack, which makes those rows
|
||||
taller, and rows there still differ by how many action buttons they stack.
|
||||
Below an 80rem card, Resource and Message cells wrap inside a `line-clamp-2`
|
||||
wrapper (`data-alert-history-cell`) instead of ending in an ellipsis after one
|
||||
line, so more of what happened reads without hover. A message or name longer
|
||||
than its two lines still ends in an ellipsis with the full text on its title;
|
||||
the table does not claim to expose every value without hover. The wrapper sets
|
||||
`whitespace-normal` itself because `.table-fixed td` forces nowrap. Message
|
||||
also keeps a two-line minimum height (`min-h-[2lh]`) so a message's length
|
||||
never changes its row's height: the shared windowing hook sizes its spacers
|
||||
from a single measured row. Scrolling a 600-row history in 60px wheel steps
|
||||
(414 tracked comparisons) moved a tracked row by exactly the scroll distance
|
||||
with uniform 49px rows, while the same history with the minimum removed (rows
|
||||
of 39px and 49px) showed 46 steps where the row jumped by up to 20px. From an
|
||||
80rem card both cells return to a one-line clamp, the single 39px row that
|
||||
card already had (`@min-[80rem]:line-clamp-1`, minimum height released).
|
||||
Measured on the mock estate in a real browser (the estate regenerates on
|
||||
every run, so the row count differs: 88 before, 90 after), messages that ended
|
||||
in an ellipsis fell from 82 of 88 rows to 24 of 90 at a 1024px window with the
|
||||
rail open (a 600px card), from 54 of 88 to 17 of 90 at 1280px, from 24 to 8 at
|
||||
1440px and from 32 to 4 at 1700px, and the median row from 75px to 49px at
|
||||
every window from 1280px to 1700px; at 2000px, where the cells keep a
|
||||
one-line clamp as before, 9 of 88 became 7 of 90. No time cell or header
|
||||
ended in an ellipsis at nine windows from 1024px to 2000px in a 12-hour
|
||||
locale. Cards narrower than 600px, which a window of about 900px with
|
||||
the rail open produces, are still cramped; a container-driven switch to the
|
||||
card list is the remaining fix.
|
||||
|
||||
Alert history row timestamps render clock time in the viewer's own locale and
|
||||
must carry the absolute date and time as a title. The date otherwise lives
|
||||
|
||||
@@ -6402,7 +6402,17 @@ The Alert History table's density tracks in `index.css` carry per-column widths
|
||||
through `--alert-history-<column>-width` custom properties set on the table at
|
||||
each density. Fixed layout sizes all nine tracks before collapsed ones are
|
||||
removed, so the visible widths sum to 100% and the table width is the sum of
|
||||
all nine; `App.architecture.test.ts` checks both at every density.
|
||||
all nine; `App.architecture.test.ts` checks both at every density, the pixel
|
||||
minimums the content-bound tracks need at the narrowest card their density
|
||||
serves, that each density block sits inside its 50rem, 64rem or 80rem
|
||||
container query, and that Message keeps at least 18% of the card. Below an
|
||||
80rem card the Alert History table's Resource and Message cells wrap in a
|
||||
`line-clamp-2` wrapper that sets `whitespace-normal` itself (the global
|
||||
`.table-fixed td` rule forces nowrap), so more of a row reads without hover on
|
||||
a row that has no disclosure to recover the rest; Message keeps a two-line
|
||||
minimum height so its length never changes a row's height, which the shared
|
||||
windowing hook's single measured row assumes, and from an 80rem card both
|
||||
cells return to a one-line clamp (`@min-[80rem]:line-clamp-1`).
|
||||
Alert History investigation detail is also responsive by interaction model,
|
||||
not only by CSS. Desktop may keep Timeline and Resource incident detail inline
|
||||
with its table row, while the virtualized phone card list must open the shared
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
{
|
||||
"version": 1,
|
||||
"base_sha": "168e82d24c9a6e4ab8e9857b365e2182ef588e9c",
|
||||
"verified_at": "2026-10-11T08:37:48Z",
|
||||
"result": "passed",
|
||||
"changed_paths": [
|
||||
"frontend-modern/src/features/alerts/AlertHistoryTableAlertRow.tsx",
|
||||
"frontend-modern/src/features/alerts/AlertHistoryTableSection.tsx",
|
||||
"frontend-modern/src/index.css"
|
||||
],
|
||||
"content_sha256": {
|
||||
"frontend-modern/src/features/alerts/AlertHistoryTableAlertRow.tsx": "3a3c38b52c7940d75a7ab12617418baf93b7e599035459fb712c583dac332701",
|
||||
"frontend-modern/src/features/alerts/AlertHistoryTableSection.tsx": "f24d5cf38babd8990672f0fe716999b8eea43c1a07625cde3b6271d0efdd3fa0",
|
||||
"frontend-modern/src/index.css": "df9316666c4dab61acd0528944690c3f8f08f890fd49bfa9efcbfea68524664c"
|
||||
},
|
||||
"routes": [
|
||||
"/alerts/history"
|
||||
],
|
||||
"viewports": [
|
||||
{
|
||||
"width": 1440,
|
||||
"height": 900
|
||||
},
|
||||
{
|
||||
"width": 1024,
|
||||
"height": 900
|
||||
},
|
||||
{
|
||||
"width": 768,
|
||||
"height": 1024
|
||||
},
|
||||
{
|
||||
"width": 390,
|
||||
"height": 844
|
||||
}
|
||||
],
|
||||
"states": [
|
||||
"mock estate of 8 nodes, 3 Docker/K8s hosts and about 90 history rows, 12-hour locale, final built bytes, headless Chromium with Liberation Sans forced (wider than most system fonts), measured at 1024, 1180, 1280, 1366, 1440, 1500, 1700, 1770 and 2000px windows (cards of 600 to 1492px) against an unpatched build of the same tree: messages ending in an ellipsis 82 of 88 -> 24 of 90 at 1024, 54 -> 17 at 1280, 24 -> 8 at 1440, 32 -> 4 at 1700, 9 -> 7 at 2000; median row 75px -> 49px from 1280 to 1700 with median equal to max (uniform rows); wide cards keep their 39px single-line row; no clipped time cell or header at any of the nine widths",
|
||||
"1024px window with the rail open (600px card): Message 142px and wrapped, three actions still stacked so rows stay 75 to 105px, no clipped header",
|
||||
"768px window: table renders with Time, Resource, Severity, Message, Status and Actions, no horizontal scroll, Timeline and Resource panels open and close",
|
||||
"390px phone: the card list renders as before, no horizontal overflow, no page errors",
|
||||
"600-row mocked history (windowing active, 139 rows mounted) scrolled in 60px wheel steps tracking one row: uniform 49px rows gave 0 jumps over 3px in 414 comparisons; the same page with the message minimum height stripped (rows of 39px and 49px) gave 46 jumps up to 20px",
|
||||
"the in-app browser with system fonts was used for the unpatched table at 1024px (Message 109px, 105px rows) and an earlier patched build, not the final bytes"
|
||||
],
|
||||
"interactions": [
|
||||
"clicked Timeline on a row (one extra panel row appeared, button read Hide), clicked again (panel row removed), clicked Resource (panel row appeared) at 1440 and 768, identical to the unpatched build",
|
||||
"focused the Timeline button with element.focus() and confirmed it is focusable and keeps focus (no key presses were sent)",
|
||||
"read each message cell title against its text on 20 rows",
|
||||
"put the base file back for the row markup, the section header, the width blocks and the 50rem switch point in turn and confirmed the matching proof fails each time, then restored byte-equal"
|
||||
]
|
||||
}
|
||||
@@ -1182,4 +1182,98 @@ describe('Alert History column widths', () => {
|
||||
expect(Number(block[2])).toBeCloseTo(allSum, 6);
|
||||
});
|
||||
});
|
||||
|
||||
// Each density is sized for the narrowest card it serves, from the natural
|
||||
// widths measured in a real browser (padding included): "08:27 AM" in a 14px
|
||||
// monospace, the Severity/Duration/Resource headers, a 119px "acknowledged"
|
||||
// badge, and the three row actions on one line (177px). Below 800px the
|
||||
// actions stack, so the base density only needs the widest single button.
|
||||
// Message, the column that says what happened, takes what is left and may
|
||||
// never fall under 18% of the card: equal shares had held it to the width
|
||||
// of the timestamp. Type and Node, which appear from 1024px, get a floor too.
|
||||
const wideNeeds = {
|
||||
timestamp: 84,
|
||||
resource: 93,
|
||||
severity: 86,
|
||||
duration: 91,
|
||||
status: 119,
|
||||
actions: 177,
|
||||
} as const;
|
||||
const pixelNeeds: Array<{
|
||||
name: string;
|
||||
cardWidth: number;
|
||||
needs: Partial<Record<(typeof columns)[number], number>>;
|
||||
}> = [
|
||||
{
|
||||
name: 'base',
|
||||
cardWidth: 600,
|
||||
needs: { timestamp: 84, resource: 93, severity: 86, status: 119, actions: 80 },
|
||||
},
|
||||
{ name: '50rem', cardWidth: 800, needs: wideNeeds },
|
||||
{ name: '64rem', cardWidth: 1024, needs: { ...wideNeeds, type: 108, node: 68 } },
|
||||
{ name: '80rem', cardWidth: 1280, needs: { ...wideNeeds, type: 108, node: 68 } },
|
||||
];
|
||||
|
||||
it('declares each density block inside its 50rem, 64rem and 80rem container query', () => {
|
||||
const enclosing = blocks.slice(1).map((block) => {
|
||||
const start = block.index as number;
|
||||
const queries = [
|
||||
...appStylesSource.slice(0, start).matchAll(/@container \(min-width: ([\d.]+)rem\) \{/g),
|
||||
];
|
||||
const query = queries[queries.length - 1];
|
||||
// Walk the braces from the query to the end of its body: the density
|
||||
// block only counts if it sits before that closing brace.
|
||||
let depth = 0;
|
||||
let close = -1;
|
||||
for (
|
||||
let index = (query.index as number) + query[0].length - 1;
|
||||
index < appStylesSource.length;
|
||||
index += 1
|
||||
) {
|
||||
const char = appStylesSource[index];
|
||||
if (char === '{') depth += 1;
|
||||
if (char === '}') depth -= 1;
|
||||
if (depth === 0) {
|
||||
close = index;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return { rem: Number(query[1]), enclosed: start + block[0].length <= close };
|
||||
});
|
||||
expect(enclosing).toEqual([
|
||||
{ rem: 50, enclosed: true },
|
||||
{ rem: 64, enclosed: true },
|
||||
{ rem: 80, enclosed: true },
|
||||
]);
|
||||
});
|
||||
|
||||
it('gives every column the pixels its content needs at the narrowest card of each density', () => {
|
||||
blocks.forEach((block, index) => {
|
||||
const widths = Object.fromEntries(
|
||||
[...block[1].matchAll(/--alert-history-([a-z]+)-width: ([\d.]+)%;/g)].map((match) => [
|
||||
match[1],
|
||||
Number(match[2]),
|
||||
]),
|
||||
);
|
||||
const { name, cardWidth, needs } = pixelNeeds[index];
|
||||
for (const [column, need] of Object.entries(needs)) {
|
||||
const pixels = (widths[column] / 100) * cardWidth;
|
||||
expect(pixels, `${name}: ${column} track at ${cardWidth}px`).toBeGreaterThanOrEqual(
|
||||
need - 0.5,
|
||||
);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
it('keeps Message at least 18% of the card at every density', () => {
|
||||
blocks.forEach((block, index) => {
|
||||
const widths = Object.fromEntries(
|
||||
[...block[1].matchAll(/--alert-history-([a-z]+)-width: ([\d.]+)%;/g)].map((match) => [
|
||||
match[1],
|
||||
Number(match[2]),
|
||||
]),
|
||||
);
|
||||
expect(widths.message, `${densities[index].name}: message share`).toBeGreaterThanOrEqual(18);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -17,6 +17,19 @@ import type { AlertHistoryState } from './useAlertHistoryState';
|
||||
|
||||
type AlertHistoryAlert = ReturnType<AlertHistoryState['groupedAlerts']>[number]['alerts'][number];
|
||||
|
||||
// Below an 80rem card the cells that say which resource and what happened wrap
|
||||
// instead of ending in an ellipsis after one line. Message then holds two lines,
|
||||
// so its length never changes the row's height: the windowing hook sizes its
|
||||
// spacers from one measured row, and rows of mixed heights make a long history
|
||||
// jump as it scrolls. From an 80rem card the message track is wide enough for
|
||||
// one line, so both cells return to a one-line clamp, the single-line row the
|
||||
// other platform tables keep. Text past its lines ends in an ellipsis and keeps
|
||||
// its title.
|
||||
const ALERT_HISTORY_MESSAGE_TEXT_CLASS =
|
||||
'line-clamp-2 min-h-[2lh] @min-[80rem]:line-clamp-1 @min-[80rem]:min-h-0 whitespace-normal wrap-break-word text-base-content';
|
||||
const ALERT_HISTORY_RESOURCE_TEXT_CLASS =
|
||||
'line-clamp-2 @min-[80rem]:line-clamp-1 whitespace-normal wrap-break-word text-base-content';
|
||||
|
||||
interface AlertHistoryTableAlertRowProps {
|
||||
alert: AlertHistoryAlert;
|
||||
state: AlertHistoryState;
|
||||
@@ -42,11 +55,18 @@ export function AlertHistoryTableAlertRow(props: AlertHistoryTableAlertRowProps)
|
||||
{props.state.formatAlertRowTime(props.alert.startTime)}
|
||||
</TableCell>
|
||||
|
||||
<TableCell
|
||||
class={`${getPlatformTableCellClassForKind('name')} max-w-[150px] truncate font-medium text-base-content`}
|
||||
title={props.alert.resourceName}
|
||||
>
|
||||
{props.alert.resourceName}
|
||||
{/* The row has no disclosure of its own, so the two cells that say
|
||||
which resource and what happened wrap instead of ending in an
|
||||
ellipsis; the title still carries the full text. The wrapper opts
|
||||
back into wrapping because `.table-fixed td` forces nowrap. */}
|
||||
<TableCell class={`${getPlatformTableCellClassForKind('name')} font-medium`}>
|
||||
<div
|
||||
class={ALERT_HISTORY_RESOURCE_TEXT_CLASS}
|
||||
data-alert-history-cell="resource"
|
||||
title={props.alert.resourceName}
|
||||
>
|
||||
{props.alert.resourceName}
|
||||
</div>
|
||||
</TableCell>
|
||||
|
||||
<TableCell
|
||||
@@ -66,11 +86,14 @@ export function AlertHistoryTableAlertRow(props: AlertHistoryTableAlertRowProps)
|
||||
</span>
|
||||
</TableCell>
|
||||
|
||||
<TableCell
|
||||
class={`${getPlatformTableCellClassForKind('text')} max-w-[300px] truncate text-base-content`}
|
||||
title={descriptionCopy().title}
|
||||
>
|
||||
{descriptionCopy().text}
|
||||
<TableCell class={getPlatformTableCellClassForKind('text')}>
|
||||
<div
|
||||
class={ALERT_HISTORY_MESSAGE_TEXT_CLASS}
|
||||
data-alert-history-cell="message"
|
||||
title={descriptionCopy().title}
|
||||
>
|
||||
{descriptionCopy().text}
|
||||
</div>
|
||||
</TableCell>
|
||||
|
||||
<TableCell
|
||||
|
||||
@@ -73,7 +73,7 @@ export function AlertHistoryTableSection(props: AlertHistoryTableSectionProps) {
|
||||
<TableHead
|
||||
class={`${getPlatformTableHeadClassForKind('text')} alert-history-timestamp-column text-[10px] font-medium uppercase tracking-wider sm:text-xs`}
|
||||
>
|
||||
Timestamp
|
||||
Time
|
||||
</TableHead>
|
||||
<TableHead
|
||||
class={`${getPlatformTableHeadClassForKind('name')} text-[10px] font-medium uppercase tracking-wider sm:text-xs`}
|
||||
|
||||
@@ -119,4 +119,45 @@ describe('AlertHistoryTableAlertRow', () => {
|
||||
'Resolved: Node temperature at 74.0°C',
|
||||
);
|
||||
});
|
||||
|
||||
// Alert History 2026-10-11: at a 1024px window the table card is 600px wide and
|
||||
// the message track about 110px, so rows read "Docker servi…" and nobody could
|
||||
// tell which alert they were looking at. The row has no disclosure of its own, so
|
||||
// the message and the resource name wrap instead of truncating; the global
|
||||
// `.table-fixed td` nowrap forces the wrapper inside the cell to opt back in.
|
||||
// Message always holds two lines so every row has one height (the windowing hook
|
||||
// sizes its spacers from a single measured row).
|
||||
it('wraps the message and resource name instead of ending in an ellipsis', () => {
|
||||
renderRow(
|
||||
historyItem({
|
||||
resourceName: 'standalone2-iso-library',
|
||||
description: "Docker service 'frontend-database' is running 1 of 2 desired tasks",
|
||||
}),
|
||||
);
|
||||
|
||||
const message = screen.getByText(
|
||||
"Docker service 'frontend-database' is running 1 of 2 desired tasks",
|
||||
);
|
||||
expect(message.dataset.alertHistoryCell).toBe('message');
|
||||
expect(message.className).toContain('line-clamp-2');
|
||||
expect(message.className).toContain('min-h-[2lh]');
|
||||
// From an 80rem card both cells return to one line at the old row height.
|
||||
expect(message.className).toContain('@min-[80rem]:line-clamp-1');
|
||||
expect(message.className).toContain('@min-[80rem]:min-h-0');
|
||||
expect(message.className).toContain('whitespace-normal');
|
||||
expect(message.className).toContain('wrap-break-word');
|
||||
expect(message.className).not.toContain('truncate');
|
||||
expect(message.closest('td')?.className).not.toContain('truncate');
|
||||
expect(message.closest('td')?.className).not.toMatch(/max-w-\[/);
|
||||
|
||||
const resource = screen.getByText('standalone2-iso-library');
|
||||
expect(resource.dataset.alertHistoryCell).toBe('resource');
|
||||
expect(resource.className).toContain('line-clamp-2');
|
||||
expect(resource.className).toContain('@min-[80rem]:line-clamp-1');
|
||||
expect(resource.className).toContain('whitespace-normal');
|
||||
expect(resource.className).toContain('wrap-break-word');
|
||||
expect(resource.className).not.toContain('truncate');
|
||||
expect(resource).toHaveAttribute('title', 'standalone2-iso-library');
|
||||
expect(resource.closest('td')?.className).not.toMatch(/max-w-\[/);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -490,11 +490,22 @@
|
||||
removed, so the table width compensates at each density to let the six,
|
||||
seven, or nine visible tracks fill the card without creating a scrollbar:
|
||||
it is the sum of all nine track widths over the sum of the visible ones.
|
||||
Visible tracks sum to 100% and are sized for the narrowest card at each
|
||||
density. Timestamp, severity, duration, status, type and node get what
|
||||
their content needs (status fits "acknowledged"), actions keep their two
|
||||
buttons in at most two lines, and message, the column that says what
|
||||
happened, takes most of what is left. At 80rem actions fit on one line.
|
||||
Visible tracks sum to 100%. Each density is sized for the narrowest card
|
||||
it serves (600px, 800px, 1024px and 1280px): time ("08:27 AM" in a 14px
|
||||
monospace), severity, duration, status ("acknowledged" needs 119px with its
|
||||
cell padding), the resource header, the type badge (from 1024px) and the
|
||||
three actions on one line (177px) get the pixels their content and header
|
||||
need at that width, and message, the column that says what happened, takes
|
||||
what is left.
|
||||
App.architecture.test.ts holds those minimums. Below 800px the three
|
||||
actions stack, which makes those rows taller than the rest.
|
||||
Below an 80rem card, resource and message wrap inside their cells
|
||||
instead of ending in an ellipsis after one line. Message then occupies two
|
||||
lines (`min-h-[2lh]`) so its length never changes a row's height, which
|
||||
the single estimated row height of the shared windowing hook
|
||||
(`usePlatformWindowedItems`) needs once a history passes 140 rows; a
|
||||
message past two lines ends in an ellipsis and keeps its full text on the
|
||||
title. From an 80rem card both cells return to a one-line clamp.
|
||||
*/
|
||||
.table-scroll-shell col.alert-history-context-track,
|
||||
.table-scroll-shell col.alert-history-full-detail-track {
|
||||
@@ -507,15 +518,15 @@
|
||||
}
|
||||
|
||||
.table-scroll-shell table.alert-history-responsive-table {
|
||||
--alert-history-timestamp-width: 15.6%;
|
||||
--alert-history-resource-width: 16.7%;
|
||||
--alert-history-timestamp-width: 14%;
|
||||
--alert-history-resource-width: 15.6%;
|
||||
--alert-history-type-width: 11.8%;
|
||||
--alert-history-severity-width: 13.6%;
|
||||
--alert-history-message-width: 18.2%;
|
||||
--alert-history-severity-width: 14.4%;
|
||||
--alert-history-message-width: 22.7%;
|
||||
--alert-history-duration-width: 11.5%;
|
||||
--alert-history-status-width: 19.2%;
|
||||
--alert-history-status-width: 19.9%;
|
||||
--alert-history-node-width: 11.2%;
|
||||
--alert-history-actions-width: 16.7%;
|
||||
--alert-history-actions-width: 13.4%;
|
||||
width: 134.5%;
|
||||
}
|
||||
|
||||
@@ -614,15 +625,15 @@
|
||||
}
|
||||
|
||||
.table-scroll-shell table.alert-history-responsive-table {
|
||||
--alert-history-timestamp-width: 11.8%;
|
||||
--alert-history-resource-width: 14.3%;
|
||||
--alert-history-timestamp-width: 10.5%;
|
||||
--alert-history-resource-width: 11.7%;
|
||||
--alert-history-type-width: 11.8%;
|
||||
--alert-history-severity-width: 10.2%;
|
||||
--alert-history-message-width: 23.4%;
|
||||
--alert-history-duration-width: 11.5%;
|
||||
--alert-history-status-width: 14.5%;
|
||||
--alert-history-severity-width: 10.8%;
|
||||
--alert-history-message-width: 18.5%;
|
||||
--alert-history-duration-width: 11.4%;
|
||||
--alert-history-status-width: 14.9%;
|
||||
--alert-history-node-width: 11.2%;
|
||||
--alert-history-actions-width: 14.3%;
|
||||
--alert-history-actions-width: 22.2%;
|
||||
width: 123%;
|
||||
}
|
||||
|
||||
@@ -658,30 +669,30 @@
|
||||
}
|
||||
|
||||
.table-scroll-shell table.alert-history-responsive-table {
|
||||
--alert-history-timestamp-width: 9.3%;
|
||||
--alert-history-resource-width: 11.2%;
|
||||
--alert-history-type-width: 11.8%;
|
||||
--alert-history-severity-width: 8%;
|
||||
--alert-history-message-width: 17%;
|
||||
--alert-history-duration-width: 9%;
|
||||
--alert-history-status-width: 11.3%;
|
||||
--alert-history-node-width: 11.2%;
|
||||
--alert-history-actions-width: 11.2%;
|
||||
--alert-history-timestamp-width: 8.2%;
|
||||
--alert-history-resource-width: 9.1%;
|
||||
--alert-history-type-width: 10.7%;
|
||||
--alert-history-severity-width: 8.4%;
|
||||
--alert-history-message-width: 19%;
|
||||
--alert-history-duration-width: 8.9%;
|
||||
--alert-history-status-width: 11.6%;
|
||||
--alert-history-node-width: 6.8%;
|
||||
--alert-history-actions-width: 17.3%;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
@container (min-width: 80rem) {
|
||||
.table-scroll-shell table.alert-history-responsive-table {
|
||||
--alert-history-timestamp-width: 7.6%;
|
||||
--alert-history-resource-width: 11.2%;
|
||||
--alert-history-type-width: 9.5%;
|
||||
--alert-history-severity-width: 6.5%;
|
||||
--alert-history-message-width: 23.3%;
|
||||
--alert-history-duration-width: 7.3%;
|
||||
--alert-history-status-width: 9.2%;
|
||||
--alert-history-node-width: 11.2%;
|
||||
--alert-history-actions-width: 14.2%;
|
||||
--alert-history-timestamp-width: 6.6%;
|
||||
--alert-history-resource-width: 11.5%;
|
||||
--alert-history-type-width: 8.5%;
|
||||
--alert-history-severity-width: 6.8%;
|
||||
--alert-history-message-width: 27.7%;
|
||||
--alert-history-duration-width: 7.2%;
|
||||
--alert-history-status-width: 9.3%;
|
||||
--alert-history-node-width: 8.5%;
|
||||
--alert-history-actions-width: 13.9%;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
|
||||
@@ -532,6 +532,27 @@ describe('tab path helpers', () => {
|
||||
expect(alertHistoryTableSectionSource).toContain('alert-history-timestamp-column');
|
||||
expect(alertHistoryTableSectionSource).toContain('alert-history-full-detail-column');
|
||||
expect(alertHistoryTableAlertRowSource).toContain('alert-history-timestamp-column');
|
||||
// The time column is headed "Time", as on the phone card, because
|
||||
// "Timestamp" needed 93px and ended in an ellipsis in the time track.
|
||||
expect(alertHistoryTableSectionSource).toMatch(/>\s*Time\s*<\/TableHead>/);
|
||||
expect(alertHistoryTableSectionSource).not.toMatch(/>\s*Timestamp\s*<\/TableHead>/);
|
||||
// A history row has no disclosure, so the cells that say which resource and
|
||||
// what happened wrap instead of truncating. Only the node cell may still end
|
||||
// in an ellipsis, and a cell-level max-width would cap a track the CSS sized.
|
||||
expect(alertHistoryTableAlertRowSource).toContain('ALERT_HISTORY_MESSAGE_TEXT_CLASS');
|
||||
expect(alertHistoryTableAlertRowSource).toContain('ALERT_HISTORY_RESOURCE_TEXT_CLASS');
|
||||
// Message holds two lines on every row so the windowing hook's single
|
||||
// measured row height stays true as a long history scrolls.
|
||||
expect(alertHistoryTableAlertRowSource).toMatch(
|
||||
/ALERT_HISTORY_MESSAGE_TEXT_CLASS =\s*'line-clamp-2 min-h-\[2lh\] @min-\[80rem\]:line-clamp-1 @min-\[80rem\]:min-h-0 whitespace-normal wrap-break-word /,
|
||||
);
|
||||
expect(alertHistoryTableAlertRowSource).toMatch(
|
||||
/ALERT_HISTORY_RESOURCE_TEXT_CLASS =\s*'line-clamp-2 @min-\[80rem\]:line-clamp-1 whitespace-normal wrap-break-word /,
|
||||
);
|
||||
expect(alertHistoryTableAlertRowSource).not.toMatch(/max-w-\[\d+px\]/);
|
||||
expect(alertHistoryTableAlertRowSource).not.toMatch(
|
||||
/ALERT_HISTORY_(?:MESSAGE|RESOURCE)_TEXT_CLASS =\s*'[^']*\btruncate\b/,
|
||||
);
|
||||
expect(alertHistoryTableSectionSource).not.toContain(
|
||||
'overflow-hidden rounded-sm border border-border',
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user