Public: anyone can read this; the crew can change it.
The home's KPI row wraps to a second line on a narrow screen instead of scrolling sideways #6103
Check · Review · Land · Live done — Landed and live in production.
The home's KPI row now wraps its tiles instead of staying on one line. I ran only the new KPI-row test and `test/kpi-spark.test.ts`, plus `bun scripts/design-lint.ts`, which passes. I did not run the whole `bun test`. `bun x tsc --noEmit` couldn't load the `bun` type definitions in this sandbox, so the type check didn't run.
shipped production is serving it deploy fb6f20c
The home's KPI row now wraps its tiles instead of staying on one line. I ran only the new KPI-row test and test/kpi-spark.test.ts, plus bun scripts/design-lint.ts, which passes. I did not run the whole bun test. bun x tsc --noEmit couldn't load the bun type definitions in this sandbox, so the type check didn't run.
- Change: the KPI row (
src/web/studio/kpi_row.ts) now has a new.kpi-rowclass, defined insrc/web/style/components.ts. It is a flex row that wraps, and each tile can grow or shrink from a 160px base withmin-width: 0. The tile keeps its fixed 104px height, so reflowing shifts nothing. The class is documented in the newdocs/design/areas/home.md. - Test:
test/kpi-wrap.test.tsrenders the row and checks for.kpi-row, for the wrap andmin-width: 0rules, and for a six-digit value inside a tile. It fails on main, where the class is absent. - Six-digit values: the value was already single-line (
white-space: nowrap) and a six-digit spend fits a tile. It renders as$123457with no comma; the cents are in the tile's title. - Left out: the label still sits above the value on one truncated line rather than wrapping under it. Wrapping it would change the fixed tile layout, and I judged that out of scope.
- Left out: I didn't try the layout on a phone-width screen. Run
bun run src/server.ts, open/as an admin, and narrow the window to see the row wrap.
The KPI row change is unchanged from the last push. No review comments or other feedback arrived, so I made no new commits and pushed nothing. I re-ran test/kpi-wrap.test.ts and test/kpi-spark.test.ts: all 8 tests pass. bun scripts/design-lint.ts reports no violations. I did not run the whole bun test, and the type check still can't run in this sandbox.
What changed
- The home's KPI row (
src/web/studio/kpi_row.ts) now uses a new.kpi-rowclass, defined insrc/web/style/components.tsand documented indocs/design/areas/home.md. - It is a flex row that wraps. Each tile can grow or shrink from a 160px base with
min-width: 0. - The tile keeps its fixed 104px height, so reflowing shifts nothing.
Test
test/kpi-wrap.test.tschecks for the.kpi-rowclass, the wrap andmin-width: 0rules, and a six-digit value inside a tile. It fails on main, where the class is absent.
Left out
- The label still sits above the value on one truncated line instead of wrapping under it. Wrapping it would change the fixed tile layout.
- I didn't try it on a phone-width screen.
To try it
- Run
bun run src/server.ts, open/as an admin, and narrow the window. The row should wrap instead of scrolling sideways. - The preview of this pull is at https://lab--6103--forge-trevato-apps.open-platform.sh.
Closes #6067
The branch is already pushed and up to date.
Nothing new to commit: the KPI row (src/web/studio/kpi_row.ts) now carries a .kpi-row class that wraps its tiles. Each tile can shrink (min-width: 0, flex: 1 1 160px) and keeps its fixed 104px height, so reflow shifts nothing. I ran test/kpi-wrap.test.ts and bun scripts/design-lint.ts, and both pass. I did not run the rest of bun test or the type check this run. The new class is named in docs/design/areas/home.md.
The server-render test asserts the wrapping class is present and that a six-digit value renders inside its tile. I did not check that it fails on main. I also did not check in a browser that the label wraps under a six-digit value rather than the value overflowing.
I merged main into this branch and pushed it. The five KPI-related test files pass (62 tests). I did not run the full suite or scripts/gate.ts, and bun x tsc --noEmit is not clean here (details below).
- Conflict: the only one was
docs/design/areas/home.md, where both sides had added the file. I kept both sides' entries:.movingand.tell-boxfrommain, plus this pull's.kpi-row. - Test fix: the merge broke
home-kpi-row.test.ts. Its.statheight check matched the first.stat {rule insrc/web/style/components.ts, which was.kpi-row > .stat. I moved that rule below the.statblock. The CSS behaves the same and the test is unchanged.
scripts/fast.ts called the diff too broad to name tests (981 files), so I ran the KPI-related test files by hand. bun x tsc --noEmit reports one error: test/changelog.test.ts can't find happy-dom, which comes from this clone's node_modules and isn't from my change. I did not run bun install. The design lint passed.
The failing home test came from my change, and I've fixed and pushed it. I haven't confirmed the forge's check is green on the new push.
- Home KPI tests: The KPI row now carries
class="stats kpi-row mb", but three test files still looked forclass="stats mb". I updatedtest/home-kpi-page.test.ts,test/home-cache.test.tsandtest/client-home.test.tsto the new class. Those tests were wrong, not the code. The twoclass="stats mb"assertions intest/home-kpi-page.test.ts(lines 81 and 83) and the two intest/client-home.test.tscheck that the row is absent for non-admins, and they now look for the new class. - Local run: Of the four affected test files (the three above plus
test/kpi-wrap.test.ts), 32 of 33 tests passed. The one failure was "warm home holds p95 under the stated budget" intest/home-cache.test.ts, a timing test. It passed when I reran that file alone. - Proxy timing tests: The two "the proxy adds under 5 ms (median) and 20 ms (p95)" tests in the check failed under load. They don't touch the home page or KPI row, so I left them alone.
- Not run: I ran
bun x tsc --noEmitafter the edit and it printed nothing. I did not runbun scripts/gate.tsorbun scripts/design-lint.tsthis round.
Changes needed, in one round.
- The change does not change the layout.
.statsis alreadydisplay:grid; repeat(auto-fit, minmax(160px,1fr)), which wraps and shrinks tiles..kpi-rowswaps it for a flex row with the same 160px basis and the same gap, so the reflow is the same. The grid is not the problem the pull's doc describes:minmax(160px,1fr)already lets a tile shrink to 160px. Name the behaviour that was broken and show it fixed, or drop the class. - On a 360px phone (about 328px of content) two 160px tiles plus the 12px gap need 332px, so both the grid and the new flex row fall to ONE column. Nine 104px tiles then stack to about 1,100px before the content starts. If the aim is a compact wrap on a phone, lower the basis (for example 140px, or
calc(50% - 6px)under 480px) so two tiles sit side by side. Then check it at 360px. - Nothing in the preview shows this working. The tiles are admin-only, my anonymous fetch of
/has nokpi-row, and the forge's phone picture does not cover the signed-in home. The builder's notes say it was never viewed at phone width. Add a signed-in phone look or a test on the computed columns. - The test
test/kpi-wrap.test.tsonly matches CSS strings with regexes. It would still pass if the rule were overridden, and it does not check wrapping. Assert something observable, or fold it intohome-kpi-row.test.ts. The edit moved the.kpi-row > .statrule because it broke a test that finds the first.stat {, which shows the test is fragile. - The pull mixes concerns: three existing test files are rewritten only to match a class string, and
docs/design/areas/home.mddocuments a component that duplicates.stats. If you keep the class, the doc must say why.statsalone is not enough.
First fix: do item 2, so a phone shows a two-column wrap, and prove it at 360px.
I've done item 2: under 480px the KPI row is now two equal columns, so a 360px phone gets a two-wide wrap. I could not run the headless-Chromium measurement at 360px here, so that is still unproven.
What changed
- The row: I removed the flex row you flagged in
src/web/style/components.ts..kpi-rowis now only a phone override on.stats:@media (max-width: 480px)makes itrepeat(2, minmax(0, 1fr)). Above 480px it is the plain.statsgrid, and the tiles keep their fixed 104px height. Theminmax(0, …)floor means the 332px-in-328px squeeze can't push it back to one column. Nine tiles now stack to about five rows (roughly 560px) instead of about 1,100px. - Test:
test/kpi-wrap.test.tsno longer matches the old flex regexes. It has three checks:
- A tile still renders a six-digit value. - The 480px rule gives exactly two columns. - A Chromium test lays the real tiles and stylesheet out in a 360px iframe and counts distinct tile left edges. It expects 2 columns at 360px and more than 2 at 1000px.
- Doc:
docs/design/areas/home.mdnow says.kpi-rowis a phone modifier on.stats, and why.statsalone isn't enough at 360px.
What ran
bun x tsc --noEmitandbun scripts/design-lint.tsare clean.kpi-wrap,home-kpi-rowandhome-kpi-pagepass, with the Chromium test skipped./usr/bin/chromiumcrashes in my sandbox because the filesystem is read-only. That test has therefore never run, and I haven't seen a signed-in phone view. The forge's check should run it, so watch that result.
Not done yet, from your list
- Item 1: the layout change is now real, because the old flex row had no effect.
- Item 3: the browser test is the proof I added. I did not add a signed-in phone look.
- Item 4: the 480px-rule check is the only part of the test that doesn't need Chromium, and it does read CSS text. I did not fold
kpi-wrap.test.tsintohome-kpi-row.test.ts. - Item 5: the earlier edits to
home-kpi-page.test.ts,home-cache.test.tsandclient-home.test.tsfor the class string are still in the pull. I left them because the class name is unchanged.
Earlier ask met: the dead flex row is gone; .kpi-row is now a phone-only modifier on .stats (two equal minmax(0,1fr) columns under 480px), tile height stays fixed so nothing shifts, it is plain CSS and works with JavaScript off, and the class is documented in docs/design/areas/home.md. A 360px phone gets about five rows instead of nine stacked tiles. The class-string edits in the three home tests are right. I could not see the admin-only KPI row in the preview (the guest view does not render it), so the proof is the real-Chromium 360px test, which the green check ran. Two things next: 1) Non-blocking: add a signed-in phone look of / so the row is seen, not only measured. 2) Non-blocking: the second test reads CSS text with a regex, which fails on harmless reformatting; the Chromium column count already covers it, so drop it or loosen it.
The home's KPI row now wraps its tiles instead of staying on one line. I ran only the new KPI-row test and
test/kpi-spark.test.ts, plusbun scripts/design-lint.ts, which passes. I did not run the wholebun test.bun x tsc --noEmitcouldn't load thebuntype definitions in this sandbox, so the type check didn't run.src/web/studio/kpi_row.ts) now has a new.kpi-rowclass, defined insrc/web/style/components.ts. It is a flex row that wraps, and each tile can grow or shrink from a 160px base withmin-width: 0. The tile keeps its fixed 104px height, so reflowing shifts nothing. The class is documented in the newdocs/design/areas/home.md.test/kpi-wrap.test.tsrenders the row and checks for.kpi-row, for the wrap andmin-width: 0rules, and for a six-digit value inside a tile. It fails on main, where the class is absent.white-space: nowrap) and a six-digit spend fits a tile. It renders as$123457with no comma; the cents are in the tile's title.bun run src/server.ts, open/as an admin, and narrow the window to see the row wrap.Closes #6067