fix(ui): keep api tokens table on screen at phone widths #6

Merged
exler merged 1 commit from fix/api-tokens-table-mobile into main 2026-10-04 18:37:36 +02:00
Collaborator

Summary

The API tokens table overflowed the page on phones: the six-column table had no scroll container and no minimum width, so it could not shrink below its min-content size, spilled out of its card and widened the document. The whole page (navigation included) shifted sideways and the Revoke button ended up off screen.

Root cause

users/templates/users/api_tokens.html rendered <table class="w-full text-xs"> directly inside the .card-neo panel. A table's minimum width is the sum of its columns' min-content widths, so w-full could not compress it at 390px. Nothing constrained the overflow, and the card does not clip, so the overflow propagated to the document.

Measured before the fix at a 390x844 viewport: document scrollWidth 514 vs clientWidth 390 -> 124px of horizontal page overflow; the table was 459px wide against a ~280px card content box; the Revoke button's right edge sat at 514px, outside the viewport.

Changes

  • users/templates/users/api_tokens.html - table wrapped in a .table-scroll container and given min-w-[34rem], so it scrolls horizontally inside its card while columns stay readable. Token, Created, Expires and Status cells are whitespace-nowrap so values do not break mid-token or mid-date.
  • dome/static/css/base.tailwind - new .table-scroll component (w-full max-w-full overflow-x-auto) with an intent comment.
  • DESIGN.md - layout rule: dense tables never widen the page; they scroll inside a .table-scroll container.
  • dome/static/css/base.css - recompiled with the Tailwind CLI (tailwindcss v4.3.3, --minify).

Tests and checks

  • python manage.py check -> System check identified no issues (0 silenced).
  • python manage.py test -> Ran 82 tests in 33.138s -> OK (expected failures=1)
  • git diff --check -> clean
  • Compiled CSS verified to contain .table-scroll and .min-w-\[34rem\]

Visual verification (390x844 and 1280x900)

Method: the page was rendered through Django's test client for the qa-local fixture account and loaded in a real Chromium at an emulated mobile viewport, with the compiled base.css inlined; layout was measured with getBoundingClientRect/scrollWidth. This is the real DOM of the route with real CSS, but not a live authenticated session - the fixture account has an unusable password and no credentials were typed anywhere. Local-only, gitignored SQLite database; nothing on the deployed instance was touched.

State Viewport Document overflow Table Result
before 390x844 124px 459px, no scroller page shifted, Revoke off screen
after 390x844 0px 544px, scrolls inside card (280 -> 544) page aligned, columns readable
after (scrolled) 390x844 0px same Revoke reachable in the scroller
after 1280x900 0px 618px, no scroller needed desktop unchanged

Risk / rollback

Presentation only: no routes, forms, HTMX attributes or request semantics changed. Revert the single commit to roll back. One cosmetic consequence at phone width: the table now scrolls horizontally (with a visible scrollbar under the card) instead of squeezing columns into unreadable widths.

Screenshots

Before - 390x844: page shifted sideways, 124px document overflow, Revoke off screen

Before - 390x844: page shifted sideways, 124px document overflow, Revoke off screen

After - 390x844: page aligned, 0px document overflow, table scrolls inside its card

After - 390x844: page aligned, 0px document overflow, table scrolls inside its card

After - 390x844, table scrolled right: Revoke reachable

After - 390x844, table scrolled right: Revoke reachable

After - 1280x900: desktop unchanged

After - 1280x900: desktop unchanged

## Summary The API tokens table overflowed the page on phones: the six-column table had no scroll container and no minimum width, so it could not shrink below its min-content size, spilled out of its card and widened the document. The whole page (navigation included) shifted sideways and the `Revoke` button ended up off screen. ## Root cause `users/templates/users/api_tokens.html` rendered `<table class="w-full text-xs">` directly inside the `.card-neo` panel. A table's minimum width is the sum of its columns' min-content widths, so `w-full` could not compress it at 390px. Nothing constrained the overflow, and the card does not clip, so the overflow propagated to the document. Measured before the fix at a 390x844 viewport: document `scrollWidth` 514 vs `clientWidth` 390 -> **124px of horizontal page overflow**; the table was 459px wide against a ~280px card content box; the Revoke button's right edge sat at 514px, outside the viewport. ## Changes - `users/templates/users/api_tokens.html` - table wrapped in a `.table-scroll` container and given `min-w-[34rem]`, so it scrolls horizontally inside its card while columns stay readable. Token, Created, Expires and Status cells are `whitespace-nowrap` so values do not break mid-token or mid-date. - `dome/static/css/base.tailwind` - new `.table-scroll` component (`w-full max-w-full overflow-x-auto`) with an intent comment. - `DESIGN.md` - layout rule: dense tables never widen the page; they scroll inside a `.table-scroll` container. - `dome/static/css/base.css` - recompiled with the Tailwind CLI (`tailwindcss v4.3.3`, `--minify`). ## Tests and checks - `python manage.py check` -> `System check identified no issues (0 silenced).` - `python manage.py test` -> `Ran 82 tests in 33.138s` -> `OK (expected failures=1)` - `git diff --check` -> clean - Compiled CSS verified to contain `.table-scroll` and `.min-w-\[34rem\]` ## Visual verification (390x844 and 1280x900) Method: the page was rendered through Django's test client for the `qa-local` fixture account and loaded in a real Chromium at an emulated mobile viewport, with the compiled `base.css` inlined; layout was measured with `getBoundingClientRect`/`scrollWidth`. This is the real DOM of the route with real CSS, but **not** a live authenticated session - the fixture account has an unusable password and no credentials were typed anywhere. Local-only, gitignored SQLite database; nothing on the deployed instance was touched. | State | Viewport | Document overflow | Table | Result | |---|---|---|---|---| | before | 390x844 | 124px | 459px, no scroller | page shifted, Revoke off screen | | after | 390x844 | 0px | 544px, scrolls inside card (280 -> 544) | page aligned, columns readable | | after (scrolled) | 390x844 | 0px | same | Revoke reachable in the scroller | | after | 1280x900 | 0px | 618px, no scroller needed | desktop unchanged | ## Risk / rollback Presentation only: no routes, forms, HTMX attributes or request semantics changed. Revert the single commit to roll back. One cosmetic consequence at phone width: the table now scrolls horizontally (with a visible scrollbar under the card) instead of squeezing columns into unreadable widths. ## Screenshots **Before - 390x844: page shifted sideways, 124px document overflow, Revoke off screen** ![Before - 390x844: page shifted sideways, 124px document overflow, Revoke off screen](https://git.marut.network/attachments/4c4f645d-6e93-4927-aa13-3d8931e45fb2) **After - 390x844: page aligned, 0px document overflow, table scrolls inside its card** ![After - 390x844: page aligned, 0px document overflow, table scrolls inside its card](https://git.marut.network/attachments/e262d7ef-25ac-4095-b59e-0183c5a902f0) **After - 390x844, table scrolled right: Revoke reachable** ![After - 390x844, table scrolled right: Revoke reachable](https://git.marut.network/attachments/a424cf14-dbfc-4a4a-9bca-3c72babd0a31) **After - 1280x900: desktop unchanged** ![After - 1280x900: desktop unchanged](https://git.marut.network/attachments/e13793b0-9695-4fa0-9f5f-a083286a51dd)
fix(ui): keep api tokens table on screen at phone widths
All checks were successful
Push Docker Image / push (push) Successful in 38s
ce32c4b241
The six-column API tokens table had no scroll container and no minimum
width, so at phone widths it could not shrink below its min-content size:
it overflowed its card and widened the document, shifting the whole page
(including the nav) sideways and pushing the Revoke button off screen.

Wrap the table in a new `.table-scroll` component (w-full max-w-full
overflow-x-auto) and give the table `min-w-[34rem]` so columns stay
readable and the table scrolls horizontally inside its card. Date, token
and status cells are nowrap so values do not break mid-token.

Documented in DESIGN.md and base.tailwind; base.css recompiled.
Author
Collaborator

Visual verification

Route rendered through Django's test client for the qa-local fixture account and loaded in real Chromium at an emulated mobile viewport with the compiled base.css inlined; layout measured via scrollWidth/getBoundingClientRect.

This is the real DOM of the route with real CSS, but not a live authenticated session: the fixture account has an unusable password and no credentials were typed. Local gitignored SQLite database only; nothing on the deployed instance was touched.

Before - 390x844: page shifted sideways, 124px document overflow, Revoke off screen

Before - 390x844: page shifted sideways, 124px document overflow, Revoke off screen

After - 390x844: page aligned, 0px document overflow, table scrolls inside its card

After - 390x844: page aligned, 0px document overflow, table scrolls inside its card

After - 390x844, table scrolled right: Revoke reachable

After - 390x844, table scrolled right: Revoke reachable

After - 1280x900: desktop unchanged

After - 1280x900: desktop unchanged

<!-- visual-verification --> ## Visual verification Route rendered through Django's test client for the `qa-local` fixture account and loaded in real Chromium at an emulated mobile viewport with the compiled `base.css` inlined; layout measured via `scrollWidth`/`getBoundingClientRect`. This is the real DOM of the route with real CSS, but **not** a live authenticated session: the fixture account has an unusable password and no credentials were typed. Local gitignored SQLite database only; nothing on the deployed instance was touched. **Before - 390x844: page shifted sideways, 124px document overflow, Revoke off screen** ![Before - 390x844: page shifted sideways, 124px document overflow, Revoke off screen](https://git.marut.network/attachments/4c4f645d-6e93-4927-aa13-3d8931e45fb2) **After - 390x844: page aligned, 0px document overflow, table scrolls inside its card** ![After - 390x844: page aligned, 0px document overflow, table scrolls inside its card](https://git.marut.network/attachments/e262d7ef-25ac-4095-b59e-0183c5a902f0) **After - 390x844, table scrolled right: Revoke reachable** ![After - 390x844, table scrolled right: Revoke reachable](https://git.marut.network/attachments/a424cf14-dbfc-4a4a-9bca-3c72babd0a31) **After - 1280x900: desktop unchanged** ![After - 1280x900: desktop unchanged](https://git.marut.network/attachments/e13793b0-9695-4fa0-9f5f-a083286a51dd)
exler merged commit ce32c4b241 into main 2026-10-04 18:37:36 +02:00
exler deleted branch fix/api-tokens-table-mobile 2026-10-04 18:37:36 +02:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
exler/dome!6
No description provided.