fix(ui): unify heading help, table sizing and navigation contracts
Verified with the coordinated workspace changes by devkit full run 2026-09-08T225814-186389-0000-3e3ed7cd (all seven phases passed). This shared UI pass does not mark the individual module reviews complete.
This commit is contained in:
@@ -342,6 +342,77 @@ assertWidths(
|
||||
"growth does not resize a fixed peer merely to avoid overflow"
|
||||
);
|
||||
|
||||
const mixedPeerColumns: DataGridSizingColumn[] = [
|
||||
{ id: "first", width: 200, minWidth: 100, maxWidth: 500, resizable: true },
|
||||
{ id: "fixed", width: 120, minWidth: 120, maxWidth: 120 },
|
||||
{ id: "last", width: 300, minWidth: 100, maxWidth: 500, resizable: true },
|
||||
{ id: "actions", width: 100, sticky: "end" }
|
||||
];
|
||||
const mixedPeerBase = { first: 200, fixed: 120, last: 300, actions: 100 };
|
||||
for (const mode of ["cover", "free", "constrained"] as const) {
|
||||
const grown = resizeDataGridColumn(mixedPeerColumns, mixedPeerBase, "first", 80, mode);
|
||||
assertWidths(grown.widths,
|
||||
{ first: 280, fixed: 120, last: mode === "constrained" ? 220 : 300, actions: 100 },
|
||||
`${mode} growth crosses a fixed intermediate column without changing it`);
|
||||
const shrunk = resizeDataGridColumn(mixedPeerColumns, mixedPeerBase, "first", -80, mode);
|
||||
assertWidths(shrunk.widths,
|
||||
{ first: 120, fixed: 120, last: mode === "free" ? 300 : 380, actions: 100 },
|
||||
`${mode} shrink uses only the appropriate resizable compensation peers`);
|
||||
const limited = resizeDataGridColumn(mixedPeerColumns, mixedPeerBase, "first", 800, mode);
|
||||
assertEqual(limited.widths.fixed, 120, `${mode} exhaustion never changes the fixed intermediate track`);
|
||||
assertEqual(limited.widths.first, mode === "constrained" ? 400 : 500, `${mode} retains declared growth limits`);
|
||||
}
|
||||
|
||||
const preferredLimitColumns: DataGridSizingColumn[] = [
|
||||
{ id: "recipients", width: "minmax(320px, 1.4fr)", preferredMaxWidth: 640, resizable: true },
|
||||
{ id: "active", width: 130 },
|
||||
{ id: "delivery", width: "minmax(260px, 0.9fr)", preferredMaxWidth: 480, resizable: true },
|
||||
{ id: "attachments", width: 180 },
|
||||
...["first", "second", "third"].map((id) => ({ id, width: 190, minWidth: 160, preferredMaxWidth: 360, resizable: true })),
|
||||
{ id: "actions", width: 180, sticky: "end" }
|
||||
];
|
||||
const hardLimitColumns = preferredLimitColumns.map(({ preferredMaxWidth, ...column }) => ({ ...column, maxWidth: preferredMaxWidth }));
|
||||
for (const container of [900, 1600, 2400, 3085]) {
|
||||
assertWidths(fitDataGridColumns(preferredLimitColumns, container).widths,
|
||||
fitDataGridColumns(hardLimitColumns, container).widths,
|
||||
`preferred caps preserve the previous automatic fit at ${container}px without imposing manual caps`);
|
||||
}
|
||||
const rightPeersAtOldCaps: DataGridSizingColumn[] = [
|
||||
{ id: "recipients", width: "minmax(320px, 1.4fr)", preferredMaxWidth: 640, resizable: true },
|
||||
{ id: "fixed", width: 130, minWidth: 130, maxWidth: 130 },
|
||||
{ id: "first", width: 190, preferredMaxWidth: 360, resizable: true },
|
||||
{ id: "second", width: 190, preferredMaxWidth: 360, resizable: true },
|
||||
{ id: "actions", width: 180, sticky: "end" }
|
||||
];
|
||||
const oversizedRecipient = { recipients: 1000, fixed: 130, first: 360, second: 360, actions: 180 };
|
||||
const oldManualCaps = rightPeersAtOldCaps.map(({ preferredMaxWidth, ...column }) => ({
|
||||
...column, maxWidth: preferredMaxWidth ?? column.maxWidth
|
||||
}));
|
||||
assertEqual(resizeDataGridColumn(oldManualCaps, oversizedRecipient, "recipients", -120, "cover", 0).appliedDelta, 0,
|
||||
"regression: at the scrolled-right boundary, old field caps block shrinking an oversized recipient column");
|
||||
const shrunkAcrossPreferredCaps = resizeDataGridColumn(rightPeersAtOldCaps, oversizedRecipient, "recipients", -120, "cover", 0);
|
||||
assertWidths(shrunkAcrossPreferredCaps.widths,
|
||||
{ recipients: 880, fixed: 130, first: 420, second: 420, actions: 180 },
|
||||
"preferred field caps allow cover compensation at the right scroll boundary without moving fixed neighbors");
|
||||
assertWidths(fitDataGridColumns(rightPeersAtOldCaps, 2030, {}, shrunkAcrossPreferredCaps.widths, "cover", 2030).widths,
|
||||
shrunkAcrossPreferredCaps.widths, "committing a compensated shrink never refills the wide recipient column");
|
||||
for (const mode of ["cover", "free", "constrained"] as const) {
|
||||
const expandedField = resizeDataGridColumn(rightPeersAtOldCaps, oversizedRecipient, "first", 160, mode);
|
||||
assertEqual(expandedField.widths.first, 520, `${mode} direct resizing can exceed a presentation-only field cap`);
|
||||
assertEqual(expandedField.widths.fixed, 130, `${mode} preferred caps do not change a fixed neighbor`);
|
||||
}
|
||||
const preferredWithHardLimit: DataGridSizingColumn[] = [{ id: "text", width: 300, preferredMaxWidth: 360, maxWidth: 500, resizable: true }];
|
||||
assertEqual(resizeDataGridColumn(preferredWithHardLimit, { text: 360 }, "text", 200, "cover").widths.text, 500,
|
||||
"an explicitly declared hard maximum still bounds direct resizing beyond a preferred cap");
|
||||
assertEqual(fitDataGridColumns([{ id: "text", width: 500, preferredMaxWidth: 400, maxWidth: 300 }], 300, {}, {}, "free").widths.text, 300,
|
||||
"a preferred cap never overrides a smaller hard maximum");
|
||||
assertEqual(fitDataGridColumns([{ id: "text", width: 300, minWidth: 160, preferredMaxWidth: 100 }], 160, {}, {}, "free").widths.text, 160,
|
||||
"preferred caps never reduce a column below its hard minimum");
|
||||
assertEqual(dataGridLayoutSignature([{ id: "text", width: 190, resizable: true }], "container", "cover"),
|
||||
"v3::text:190:::r::::default:::container::cover", "omitting preferred caps preserves the existing persisted signature format");
|
||||
assertEqual(dataGridLayoutSignature(preferredLimitColumns, "container", "cover") === dataGridLayoutSignature(hardLimitColumns, "container", "cover"), false,
|
||||
"new preferred sizing declarations invalidate only their own obsolete manual-width contract");
|
||||
|
||||
const coverBeyondPassiveMax = resizeDataGridColumn([
|
||||
{ id: "first", width: 200, minWidth: 100, maxWidth: 200, resizable: true },
|
||||
{ id: "second", width: 300, minWidth: 100, maxWidth: 300, resizable: true },
|
||||
|
||||
Reference in New Issue
Block a user