mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-08 20:42:43 +00:00
fix(admin): drop whitespace-nowrap on api-tokens date cells (5th attempt)
The /admin/api-tokens page has been painting a residual horizontal scrollbar for four releases despite column-hide, mobile card-list, and the admin section-strip `no-scrollbar` fixes. A fresh production probe confirmed the actual culprit: the "Last used" and "Created" `<td>`s carry `whitespace-nowrap`, and `formatDateTime` renders strings like "05.05.2026, 21:46" (~110px) that exceed the 12% colgroup allotment (~84px on a 700px content area). `whitespace-nowrap` wins over `table-fixed`'s width contract, so the table's intrinsic width exceeds 100% and the wrapping `overflow-x-auto` paints the scrollbar. Dropping the two `whitespace-nowrap` classes lets the date+time wrap to two lines on narrow viewports. The card grows by one row but no scrollbar — and at >1024px desktop the unwrapped string already fits in the 12% allotment so the visual is unchanged for the common case. Picked option 1 of the three W1a probe found (drop nowrap, switch to formatDateShort, or hide "Created" at md): smallest two-line diff, no i18n surface impact, no information loss. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
a22f77881e
commit
1643a78f63
2 files changed
+43
-2
No files matched your search
@@ -122,6 +122,34 @@ describe("ApiTokenOverviewSection — responsive", () => {
|
|||||||
expect(html).toMatch(/class="[^"]*\bp-4\b[^"]*sm:p-6/);
|
expect(html).toMatch(/class="[^"]*\bp-4\b[^"]*sm:p-6/);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("desktop date cells drop whitespace-nowrap (v1.4.22 C2 5th-attempt fix)", () => {
|
||||||
|
const html = render();
|
||||||
|
// The "Last used" + "Created" `<td>`s no longer carry
|
||||||
|
// `whitespace-nowrap`. The v1.4.19 production probe confirmed that
|
||||||
|
// class was the actual culprit behind the residual horizontal
|
||||||
|
// scrollbar at 768-1280px: a formatted date+time string
|
||||||
|
// ("05.05.2026, 21:46") overflowed its 12% colgroup allotment
|
||||||
|
// (~84px on a 700px content area) and won over `table-fixed`'s
|
||||||
|
// width contract, so the table's intrinsic width exceeded 100%
|
||||||
|
// and the wrapping `overflow-x-auto` painted a scrollbar. Letting
|
||||||
|
// the cell wrap to two lines costs one row of height but kills
|
||||||
|
// the bar.
|
||||||
|
const tableMatch = html.match(/<table[\s\S]*?<\/table>/);
|
||||||
|
expect(tableMatch).not.toBeNull();
|
||||||
|
const tableMarkup = tableMatch![0];
|
||||||
|
// Pick every <td> inside the desktop table that renders one of the
|
||||||
|
// two date columns (text-right + text-xs is unique to those cells)
|
||||||
|
// and assert none carries whitespace-nowrap.
|
||||||
|
const dateCellMatches =
|
||||||
|
tableMarkup.match(
|
||||||
|
/<td[^>]*\btext-right\b[^>]*\btext-xs\b[^>]*>/g,
|
||||||
|
) ?? [];
|
||||||
|
expect(dateCellMatches.length).toBeGreaterThanOrEqual(2);
|
||||||
|
for (const cell of dateCellMatches) {
|
||||||
|
expect(cell).not.toContain("whitespace-nowrap");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
it("mobile timestamp lines wrap (no nowrap on the meta paragraphs)", () => {
|
it("mobile timestamp lines wrap (no nowrap on the meta paragraphs)", () => {
|
||||||
const html = render();
|
const html = render();
|
||||||
const mobileMatch = html.match(/<ul[^>]*md:hidden[^>]*>([\s\S]*?)<\/ul>/);
|
const mobileMatch = html.match(/<ul[^>]*md:hidden[^>]*>([\s\S]*?)<\/ul>/);
|
||||||
|
|||||||
@@ -222,12 +222,25 @@ export function ApiTokenOverviewSection() {
|
|||||||
</Badge>
|
</Badge>
|
||||||
)}
|
)}
|
||||||
</td>
|
</td>
|
||||||
<td className="text-muted-foreground px-3 py-2 text-right text-xs whitespace-nowrap">
|
{/* v1.4.22 C2 (5th attempt) — drop
|
||||||
|
`whitespace-nowrap` on the date cells. The
|
||||||
|
v1.4.19 A7 probe confirmed `formatDateTime`
|
||||||
|
renders "05.05.2026, 21:46" (~110px) which
|
||||||
|
exceeds the 12% `<col>` allotment (~84px on
|
||||||
|
a 700px content area); `whitespace-nowrap`
|
||||||
|
wins over `table-fixed`'s width contract,
|
||||||
|
so the table's intrinsic width exceeds 100%
|
||||||
|
and the wrapper's `overflow-x-auto` paints
|
||||||
|
the scrollbar the maintainer kept reporting
|
||||||
|
for the 5th time. Letting the date+time
|
||||||
|
wrap to two lines on narrow viewports costs
|
||||||
|
one row of height but eliminates the bar. */}
|
||||||
|
<td className="text-muted-foreground px-3 py-2 text-right text-xs">
|
||||||
{token.lastUsedAt
|
{token.lastUsedAt
|
||||||
? formatDateTime(token.lastUsedAt)
|
? formatDateTime(token.lastUsedAt)
|
||||||
: t("admin.tokenNeverUsed")}
|
: t("admin.tokenNeverUsed")}
|
||||||
</td>
|
</td>
|
||||||
<td className="text-muted-foreground px-3 py-2 text-right text-xs whitespace-nowrap">
|
<td className="text-muted-foreground px-3 py-2 text-right text-xs">
|
||||||
{formatDate(token.createdAt)}
|
{formatDate(token.createdAt)}
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|||||||
Reference in new issue
Block a user