fix(homepage): uniform 4-column grid, hold the status gutter, unleak AI Systems
The board's card width changed at every group boundary because `columns:` was being tuned per group under the 2026-08-18 "columns = member count" rule. That rule is retired: it sets `lg:grid-cols-N` for one group, so it fixes that group's CARD WIDTH, not its density. Measured on the live board, Notes rendered a single 1464px card, News and Media 728px, Eval & Retrieval 286px, everything else 360px. All 20 groups are now `columns: 4` and every card renders at 360. `.service-name` reserved a 78px status gutter with `padding-right` and relied on `overflow: hidden` to hold it, but overflow clips at the PADDING box — the gutter was spill room the title printed straight through. Six cards on the AI tab rendered their name underneath their own status pill, measured by testing the title text node's box against the status cluster's. The intended ellipsis never fired either: it is painted by whichever block's own line overflows, and that is the anonymous box around the bare title text node, which does not carry `overflow`. The gutter holds by wrapping now, and the description opts back out of it with a negative margin since the pill only ever covers the first line. Scriberr's `homepage.group=AI Systems` named a group absent from `layout:`, so it had no `tab:` and rendered on all four tabs — the same defect as UltraSeedbox in 2026-08-18, arriving this time from a container label. Relabelled to `AI - Audio Tools`, where the other ASR seats already live. The `homepage.group=AI Systems` sample in the repo-root CLAUDE.md was the source of the name and now carries the constraint, plus the fact that a labelled container is discovered from any of the five configured engines and must not also be listed in services.yaml. Also: descriptions clamped to three lines so a five-line outlier stops dragging its row 50px taller than its neighbours; icon ramp overridden off slate-400 -> slate-700, which was sinking the bottom half of every glyph into the card fill; bookmark groups and Jellyfin's trailing stream rows brought into the card and eyebrow vocabulary; group gap 10px -> 22px now that width no longer separates them. The icon override sits on `html[class]`, not `:root`: Homepage sets the same variables on `.theme-slate`, which is on the <html> element, and a class beats `:root` on the same element. Verified with Playwright against the live board — per-group card width, card height spread, and a geometric title-vs-status collision check, before and after. Before/after captures: http://10.100.10.50:8090/b/homepage-relayout/
This commit is contained in:
@@ -82,14 +82,60 @@ Three fixes, all in this stack's config except where noted:
|
||||
they had members, so the last row of each was mostly dead space (Notes: 1
|
||||
card in a 4-wide row). Columns now track member counts; see the rule in
|
||||
`settings.yaml`. Check with `GET /api/services`, which prints live per-group
|
||||
counts.
|
||||
counts. ⚠ **Superseded 2026-08-24** — see below.
|
||||
|
||||
## 2026-08-24 layout + theme pass
|
||||
|
||||
- **Columns are 4 everywhere now; "columns = member count" is retired.**
|
||||
`columns:` sets `lg:grid-cols-N` for one group, so tuning it per group fixes
|
||||
that group's *card width* — and the width then changed at every group
|
||||
boundary. Measured on the live board: Notes rendered a single 1464px card,
|
||||
News and Media 728px, the AI tab alternated 360 / 728 / 286 down the page.
|
||||
The old rule was avoiding dead cells in a short last row and bought a worse
|
||||
defect. A short last row is what a grid looks like; a card wider than its
|
||||
neighbours is what a mistake looks like. Rule and reasoning are at the top of
|
||||
`settings.yaml`'s `layout:` block.
|
||||
- **Scriberr's `AI Systems` group was on all four tabs** — the same untabbed-
|
||||
group behaviour as UltraSeedbox in 2026-08-18, arriving this time from a
|
||||
container label rather than from this file. Relabelled to `AI - Audio Tools`
|
||||
in `stacks/scriberr/compose.yaml` (its real home, alongside Parakeet and
|
||||
Speaches) and the container recreated. The `homepage.group=AI Systems` sample
|
||||
in the repo-root `CLAUDE.md` was the source and now carries the constraint.
|
||||
- **Long service names printed under their own status pill.** `.service-name`
|
||||
reserved a 78px right gutter with `padding-right` and relied on
|
||||
`overflow: hidden` to hold it — but overflow clips at the *padding* box, so
|
||||
the gutter was spill room, not a guard. Every long name on the AI tab
|
||||
collided. It holds by wrapping now; see the comment on the rule.
|
||||
- **Descriptions are clamped to three lines** (floor of two, unchanged). Four-
|
||||
and five-line descriptions were dragging their whole row 30-50px taller than
|
||||
the cards beside them.
|
||||
- **Icons were grey smudges.** Homepage masks every mdi glyph over
|
||||
`--color-logo-start/stop`, stock slate-400 → slate-700, and the dark stop
|
||||
sank the bottom of each glyph into the card fill. Overridden to ice → aurora
|
||||
blue. ⚠ The override must sit on `html[class]`, not `:root` — Homepage sets
|
||||
the same variables on `.theme-slate`, which is on `<html>`, and a class beats
|
||||
`:root` on the same element.
|
||||
- **Bookmark groups and Jellyfin's trailing stream rows** were the last two
|
||||
un-themed components; both now use the card/eyebrow vocabulary.
|
||||
|
||||
Verified with Playwright against the live board — per-group card width, card
|
||||
height spread, and a geometric title-vs-status collision check. Script pattern
|
||||
is in the "iteration loop" note below.
|
||||
|
||||
## The tab bar goes missing after a recreate, then comes back on its own
|
||||
|
||||
**Status: self-healing, cause not pinned. Do not chase it.** After a recreate
|
||||
the client render comes up with no tab bar, no wallpaper and no i18n (the
|
||||
search box shows the raw key `search.search`), and groups fall back to
|
||||
side-by-side columns. It restores itself with no intervention.
|
||||
**Status: self-healing, cause not pinned, and INTERMITTENT. Do not chase it.**
|
||||
After a recreate the client render can come up with no tab bar, no wallpaper
|
||||
and no i18n (the search box shows the raw key `search.search`), with groups
|
||||
falling back to side-by-side columns. It restores itself with no intervention.
|
||||
|
||||
⚠ **It does not happen every time.** The 2026-08-24 recreate (`compose up -d
|
||||
--force-recreate homepage`, to land a `settings.yaml` change) came up correct
|
||||
within 10 seconds: the fresh `columns: 4` payload was in the served HTML on the
|
||||
first poll, and a Playwright pass clicked through all four tabs a minute later
|
||||
with the bar present. So do not pre-emptively schedule an hour of ugliness
|
||||
around a config change — recreate, check, and only then walk away if it is in
|
||||
the broken state.
|
||||
|
||||
**Timing, measured rather than assumed:** five minutes is NOT enough — a fresh
|
||||
container was still tab-less at 4m30s, twice. It was observed healthy again
|
||||
|
||||
Reference in New Issue
Block a user