fix(web): a narrow window must not widen the document (improvise-tg27)
The report was "a narrow window clips grid columns without usable horizontal
scroll", and the ticket suspected a flex `min-width: auto` trap swallowing
`#grid`'s overflow. It was not that: `#grid` has `overflow: auto`, which
already zeroes a flex item's automatic minimum. What could not shrink was the
app bar.
Measured at 22ab58f on the grouped harness fixture, `documentElement.scrollWidth`
read 1011 at every window narrower than 1011px — a floor, not a slope, which is
the signature of a sum of `flex: none` reserves. Below it the PAGE grew a
horizontal scrollbar, and what it scrolled to was the bar's own right-hand end
sitting outside the window, while the grid slid off to the left.
`header` takes `flex-wrap: wrap`, chosen over a `@media` breakpoint because a
flex item wraps exactly when the line cannot hold it, so the desktop bar is
untouched by construction rather than by a number someone picked. `main` gets
the `min-width: 0` the ticket asked about, and the three side panels are capped
at 40vw so the grid keeps the larger share of a phone window.
What this deliberately does NOT do: make `#grid` scroll to columns beyond the
announced extent. The browser's Viewport is a real window (gotcha 44/47), so
those columns are never projected and no scrolling can reveal them; the
keyboard already reaches every one, and a spec now asserts that.
`harness/tests/narrow.spec.js` asserts `scrollWidth <= clientWidth`, which is a
question a browser answers exactly. `body { overflow-x: hidden }` was rejected
for making that assertion vacuous.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FC2jVn8Au7E9JPkw6bwXXH
This commit is contained in:
+17
-1
@@ -77,6 +77,9 @@ body {
|
||||
|
||||
header {
|
||||
display: flex;
|
||||
/* The reserve is a FLOOR, so below the width that holds it the bar must
|
||||
reflow rather than widen the document (improvise-tg27). clients.md. */
|
||||
flex-wrap: wrap;
|
||||
gap: 0.75rem;
|
||||
align-items: center;
|
||||
flex: none;
|
||||
@@ -115,6 +118,8 @@ header h1 {
|
||||
#doc-name {
|
||||
flex: none;
|
||||
width: 34ch;
|
||||
/* A reserve wider than the window is not a reserve, it is an overflow. */
|
||||
max-width: 100%;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
@@ -195,7 +200,10 @@ header h1 {
|
||||
backstop for an unusually long peer address — app.js puts the whole text
|
||||
on `title`, so an ellipsis loses nothing. */
|
||||
flex: 0 0 auto;
|
||||
max-width: 52ch;
|
||||
/* 52ch is the backstop for a long peer address; `100%` is the one that
|
||||
matters on a phone, where 52ch is wider than the window and the bar
|
||||
would overflow its own line rather than wrap (improvise-tg27). */
|
||||
max-width: min(52ch, 100%);
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
@@ -384,14 +392,21 @@ header h1 {
|
||||
|
||||
/* ── The frame: panels and grid ──────────────────────────────────────── */
|
||||
|
||||
/* `min-width` as well as `min-height`: without it a flex child's automatic
|
||||
minimum is its content, and `main` would be sized by the widest panel plus
|
||||
the grid rather than by the window (improvise-tg27). */
|
||||
main {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
min-height: 0;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
/* The panels are fixed-width beside the grid, and a fixed width is a fraction
|
||||
of a narrow window: capped, the grid keeps the larger share. clients.md. */
|
||||
#categories {
|
||||
width: 15rem;
|
||||
max-width: 40vw;
|
||||
flex: none;
|
||||
overflow: auto;
|
||||
padding: 0.5rem 0.25rem;
|
||||
@@ -402,6 +417,7 @@ main {
|
||||
#formulas,
|
||||
#views {
|
||||
width: 18rem;
|
||||
max-width: 40vw;
|
||||
flex: none;
|
||||
overflow: auto;
|
||||
padding: 0.5rem 0.25rem;
|
||||
|
||||
Reference in New Issue
Block a user