From 7be41d6751e870ea07f0090543692c8a63d03ef2 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 24 Aug 2026 21:50:32 +0000 Subject: [PATCH] =?UTF-8?q?dashboard:=20an=20out-link=20label=20may=20wrap?= =?UTF-8?q?=20=E2=80=94=20the=20last=20nowrap=20that=20broke=20the=20phone?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The board family's shared theme now makes wrapping the page default (PyAutoBrain#266) and bounds its chips (PyAutoBrain#270). `white-space:nowrap` is the one thing an inherited `overflow-wrap` cannot reach, and this file has two of them. One is fed by data. `a.out` labels are built from repo names — `f"{name} run"` for a failing row, `f"{repo} {kind}"` for a hang event — and this org's longest repo name is 36 characters. Under `nowrap` that is a single unbreakable ~500px word, which sets the summary column's min-content width and takes the whole page with it. Rendered with a failing row whose link names that repo and measured in a headless Chromium: a 375px viewport scrolled to 521px, with the summary text and the details list dragged off the edge alongside the link. Dropping `nowrap` costs nothing. A short label like `run ↗` has no wrap opportunity to take, so it is unaffected; a long one now breaks instead of breaking the page, and the shared theme's `overflow-wrap` does the rest. Re-measured: 375/375 at a 390px viewport, 305/305 at 320px. `td.name` keeps its `nowrap`: those titles come from this module's own fixed vocabulary ("Libraries", "Workspace test-mode timing"), never from repo data, so it carries no such trap. 603 tests pass, including one pinning the link label. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01VhpLPmmoSFAtVpppG8azVA --- heart/dashboard.py | 10 +++++++++- tests/test_dashboard.py | 15 +++++++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/heart/dashboard.py b/heart/dashboard.py index 87ef3ac..0274197 100644 --- a/heart/dashboard.py +++ b/heart/dashboard.py @@ -1284,7 +1284,15 @@ def _html_reason(item: dict) -> str: ul.det{margin:.35rem 0 0;padding-left:1.1rem;color:var(--muted); font-size:.85rem} .ago{color:var(--muted)} -a.out{font-size:.85rem;white-space:nowrap} +/* The out-links carry DATA in their labels — ` run`, and this org's + longest repo name is 36 characters. `nowrap` made one of those a single + unbreakable 500px word, which set the summary column's min-content width + and pushed the whole page sideways on a phone (measured: a 375px viewport + scrolling to 521px). Nothing is lost by letting them wrap: a short label + like `run ↗` has no wrap opportunity to take, and a long one should break + rather than break the page. The shared theme's `overflow-wrap` does the + rest. */ +a.out{font-size:.85rem} .stale{background:var(--btn);border:1px solid var(--warn);color:var(--warn); padding:.55rem .75rem;border-radius:8px} .reasons{margin:1.5rem 0} diff --git a/tests/test_dashboard.py b/tests/test_dashboard.py index fcff740..998b01e 100644 --- a/tests/test_dashboard.py +++ b/tests/test_dashboard.py @@ -840,3 +840,18 @@ def test_html_wears_the_shared_family_theme(): assert t.ORGANS[dashboard.BOARD_KEY]["tagline"] in out assert t.ORGANS[dashboard.BOARD_KEY]["ink_dark"] in out assert "#58a6ff" not in out # the old hard-coded GitHub blue + + +def test_a_long_out_link_label_cannot_push_the_page_sideways(): + """The out-links carry DATA in their labels (` run`), and this org's + longest repo name is 36 characters. Under `white-space:nowrap` that was a + single unbreakable ~500px word: it set the summary column's min-content + width and scrolled the whole board sideways on a phone (a 375px viewport + measured 521px). Short labels have no wrap opportunity to take, so nothing + is lost by letting them break.""" + out = dashboard.render( + _failing_snapshot() if "_failing_snapshot" in globals() else make_snapshot(), + make_verdict("red", 40, red_reasons=["RepoA: CI failure"]), + fmt="html", now=FRESH_NOW) + rule = re.search(r"a\.out\{[^}]*\}", out).group(0) + assert "nowrap" not in rule