diff --git a/docs/OVERVIEW.md b/docs/OVERVIEW.md index 19f2103..e602773 100644 --- a/docs/OVERVIEW.md +++ b/docs/OVERVIEW.md @@ -298,6 +298,41 @@ module rather than CSS custom properties because `el-aside` takes its width through a prop, which would otherwise fight an inline style coming from the stylesheet. +### List pages fill the window + +A table is the page. Left alone it is as tall as its rows, so on a large screen +most of the window sits empty below the last row while the *page* is still the +thing that scrolls — the wrong half of the screen moving for a list that should +simply show more. The three list pages (`/papers`, `/templates/list`, +`/templates/fields`) therefore stretch the table to the height the window +offers, with the toolbar above it and the pagination below it staying put while +the rows scroll inside the table. + +It is CSS only — no resize listener, no measured pixel height, nothing to go +stale when the rail collapses or the window changes. Four links carry it, and +each one is load-bearing: + +| Piece | Why | +|---|---| +| `.page--fill` | `min-height: 100%` of the content area — a floor that still grows | +| `.card--fill` | makes the card a column so its body can pass the height down | +| `.card--fill > .el-card__body` | a column with `min-height: 0`, without which a flex child refuses to shrink below its content | +| `.table-fill` + `height="100%"` | `flex: 1 1 0` so the table takes the leftover height instead of claiming its content height as its basis; Element Plus then pins the header and scrolls the rows | + +Measured in a real browser at three window sizes, with rows to scroll and with +none: + +| Window | Table | Page scroll | Rows scroll | Empty state | +|---|---|---|---|---| +| 1920x1080 | 781px | none | 519px inside | centred, 741px | +| 1440x900 | 601px | none | 699px inside | centred, 561px | +| 1280x620 | 321px | none | 979px inside | centred, 281px | + +`.table-fill` keeps a 240px floor. Below it — a 1280x420 window — the table +stops shrinking, the page grows past the viewport and the content area scrolls, +which is the pre-existing behaviour rather than a squashed table. Pages that +are not lists (the paper document) keep scrolling normally. + ### Routes | Path | View | Section | diff --git a/frontend/src/styles/base.css b/frontend/src/styles/base.css index 16bcaf6..a2e07d7 100644 --- a/frontend/src/styles/base.css +++ b/frontend/src/styles/base.css @@ -202,3 +202,60 @@ samp { justify-content: flex-end; margin-top: 16px; } + +/* --- list pages that fill the viewport -------------------------------------- + A list page is a table with controls around it. Left alone, the table is as + tall as its rows, so on a large screen most of the window sits empty under + the last row while the page is still the thing that scrolls. These three + classes make the table take the height the window offers instead: more rows + visible at once on a big screen, and the height given back on a small one. + + Every link in the chain is load-bearing: + + .page--fill `min-height`, never `height` + .card--fill a column, so its body can pass the height on + .card--fill > .el-card__body + a column too, and `min-height: 0` — without it + a flex child refuses to shrink below its + content and the table would never get a height + .table-fill `flex: 1 1 0`, i.e. basis 0. With `auto` the + table would claim its content height as its + basis and push the pagination out of the card + el-table height="100%" fills .table-fill; Element Plus then keeps the + header fixed and scrolls the rows internally + + `.page--fill` is a *minimum*, not a fixed height: on a short window the + table keeps its 240px floor, the page grows past the viewport and the + content area scrolls, which is the behaviour a squeezed table would not + survive. */ + +.page--fill { + min-height: 100%; +} + +.card--fill { + /* Basis auto, so the card fills the page's minimum height exactly and still + grows if its content needs more. */ + flex: 1 1 auto; + display: flex; + flex-direction: column; + min-height: 0; +} + +.card--fill > .el-card__header { + flex: 0 0 auto; +} + +.card--fill > .el-card__body { + flex: 1 1 auto; + min-height: 0; + display: flex; + flex-direction: column; +} + +.table-fill { + /* `1 1 0` rather than `1 1 auto`: the table takes the leftover height rather + than adding to it. The min-height is the floor a short window lands on. */ + flex: 1 1 0; + min-height: 240px; +} diff --git a/frontend/src/views/PapersView.vue b/frontend/src/views/PapersView.vue index bc113ab..edcfa06 100644 --- a/frontend/src/views/PapersView.vue +++ b/frontend/src/views/PapersView.vue @@ -168,8 +168,8 @@ onMounted(async () => {