From 48f1f70c1c566c9c599beae752ece960e7ad441a Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 24 Aug 2026 21:59:54 +0000 Subject: [PATCH] board: on a phone a table row is a card, not a ribbon MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The sideways scroll is gone, and what it was hiding is now the problem: a four-column row does not fit a phone, it just stops overflowing. Measured on the Mind dashboard's Recent feed at a 375px viewport, the meta columns took 156px and the text was left 187 — half the screen — so every entry wrapped into a tall thin column down the right while `when` and `what` sat beside it as empty height. The Heart board is the same shape and worse: its summary had 213px of 390 and one row ran 472px down the screen. Below 34rem the row stacks instead. The meta cells read as one small header line with the 📋 at its end, and the text takes a full-width line underneath: 187px -> 343px on the Mind feed, and each board's own cells fall into the same frame (the Heart's dot and title lead, its summary follows). `:not([hidden])` on the flex rule is load-bearing rather than defensive: `display:flex` outranks the UA sheet's `[hidden]{display:none}`, so a bare `table.recent tr` selector reveals the whole paged Recent feed at once — 50 rows instead of 10. Caught by the page growing from 6.3k to 11.5k pixels between two renders; pinned by a test. 469 tests pass, three new (the stack, the text's full-width line, the hidden guard). The wide layout is untouched — the media query is the only new selector above 34rem. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01VhpLPmmoSFAtVpppG8azVA --- board/_theme.py | 17 +++++++++++++++++ tests/test_board_theme.py | 20 ++++++++++++++++++++ 2 files changed, 37 insertions(+) diff --git a/board/_theme.py b/board/_theme.py index 519cad6..7f0aabf 100644 --- a/board/_theme.py +++ b/board/_theme.py @@ -429,6 +429,23 @@ def mark(key): padding-top:.58rem} table.recent td.pick{width:2.6rem;padding-right:0} table.recent button.copy{width:2.2rem;height:2.2rem;font-size:.95rem} +/* On a phone a four-column row is not a row, it is a ribbon. Measured at a + 375px viewport: the meta columns took 156px and the text was left 187 — half + the screen — so every entry wrapped into a tall thin column down the right + while the meta cells sat beside it as empty height. Below 34rem the row + stacks: the meta reads as one small header line with the button at its end, + and the text takes the full width underneath. */ +@media(max-width:34rem){ + /* `:not([hidden])` is load-bearing: `display:flex` here outranks the UA + sheet's `[hidden]{display:none}`, which would reveal the whole paged + Recent feed at once. */ + table.recent tr:not([hidden]){display:flex;flex-wrap:wrap;align-items:baseline;gap:0 .5rem; + padding:.5rem 0;border-bottom:1px solid var(--line)} + table.recent td{display:block;width:auto;border-bottom:0;padding:0} + table.recent td.what{padding-top:0} + table.recent td.pick{width:auto;margin-left:auto} + table.recent td:not([class]){flex:1 0 100%%;margin-top:.15rem} +} /* --- the family footer: one chip per sibling board, in its own colour --- */ .boards{display:flex;flex-wrap:wrap;gap:.4rem;margin:2.4rem 0 0;padding:0; list-style:none;border-top:1px solid var(--line);padding-top:1rem} diff --git a/tests/test_board_theme.py b/tests/test_board_theme.py index 4279c72..5ce1d5d 100644 --- a/tests/test_board_theme.py +++ b/tests/test_board_theme.py @@ -220,3 +220,23 @@ def test_a_pill_is_bounded_because_nowrap_is_outside_the_wrap_guard(): # overflow:hidden moves an inline-block's baseline to its bottom edge, so # the old optical nudge would drop every chip half a line. assert "vertical-align:bottom" in flat + + +def test_the_narrow_screen_stack_never_reveals_the_paged_feed(): + """`display:flex` on a row outranks the UA sheet's `[hidden]{display:none}`, + so a bare `table.recent tr` selector would unhide every row the Recent + feed pages behind its '… more' button — 50 rows instead of 10.""" + css = _theme.css("mind") + stack = re.search(r"@media\(max-width:34rem\)\{.*?\n\}", css, re.S).group(0) + assert "table.recent tr:not([hidden]){display:flex" in stack.replace("\n ", "") + assert "table.recent tr{display:flex" not in css + + +def test_a_row_stacks_on_a_phone_so_the_text_gets_the_width(): + """Four columns on a 375px screen left the text 187px and ran each entry + down the right as a ribbon; below 34rem the meta leads and the text takes + a full-width line of its own.""" + stack = re.search(r"@media\(max-width:34rem\)\{.*?\n\}", _theme.css("mind"), + re.S).group(0).replace("\n ", "") + assert "table.recent td{display:block;width:auto" in stack + assert "table.recent td:not([class]){flex:1 0 100%" in stack