tabs.js + docs: migrate icon + pending-state prose to docs (#712 batch 11)
Mara on #774: previous batches were cookie-stripping rather than prose migration. This batch actually moves substantive comment prose from tabs.js into docs/web-ui.md. Moved to docs/web-ui.md: - Container row → **Icon layout + load strategy** sub-paragraph (new): absolute-positioning rationale (so img load state can't reflow row), fire-and-forget load pattern (no pre-check reachability), favicon fallback chain, icon-unreachable class, the immediate-fallback-when-stopped optimisation. - Container row → **Pending-state derivation** paragraph (new): three-source priority order (transient → in-flight queue → none), why ContainerStateChanged isn't enough, the opRunning flag's role in driving the pending-running class + spinner. Collapsed in tabs.js: - Icon block (~14 lines of WHY comments + pointer to docs) → 4-line pointer + behavioural one-liner. Drops #177 / #195 / #202 cookies en passant since their substance now lives in docs. - Pending-state block (~22 lines split across two paragraphs) → 4-line pointer. Drops #769 self-cookie (the queued vs running split lives in docs::Container row now). - SharedWorker EventSource (~7 lines) → 5-line pointer. Drops #448 cookie (the SSE multiplexing paragraph in docs already has the design + Firefox throttling rationale; the in-code comment was duplicating). - M4TR1X tab gating (~4 lines) → 2-line pointer. Drops #607 cookie in both tabs.js + docs/web-ui.md::Tab strip (the substance was already in docs, just had the cookie attached). tabs.js: 11 → 6 refs (92% reduction from baseline 73). Net effect: ~47 lines of substantive prose moved out of tabs.js into docs/web-ui.md, where it belongs.
This commit is contained in:
parent
68c2b3284e
commit
ea1c6e4d05
2 changed files with 48 additions and 41 deletions
|
|
@ -193,7 +193,7 @@ cross-page link (`◆ FL0W ◆ →`), not a pane swap.
|
|||
`services.hyperhive.matrix.gui.enable` is off (defaults to
|
||||
`matrix.enable`) so operators without the matrix GUI on don't
|
||||
see a dead link — tabs.js gates the `hidden` attribute on
|
||||
`state.matrix_gui_enabled` from `/api/state` (#607).
|
||||
`state.matrix_gui_enabled` from `/api/state`.
|
||||
- **Notification controls**: `🔔 enable notifications` when
|
||||
permission ungranted; `🔕 mute / 🔔 unmute` toggle once granted.
|
||||
Always visible in the chrome regardless of active tab.
|
||||
|
|
@ -404,6 +404,23 @@ falls back to the dimmed hyperhive mark (`/favicon.svg`). The card
|
|||
body sits to the right with three stacked lines
|
||||
(`assets/tabs.js::renderContainers`).
|
||||
|
||||
**Icon layout + load strategy:** the `<img>` is absolutely
|
||||
positioned (`inset: 0`) inside the `.container-icon` wrapper —
|
||||
the wrapper is the flex child and sizes itself via `width: 5em` +
|
||||
`aspect-ratio: 1`, the `<img>` is out of flow so its load state
|
||||
(pending, loaded, broken) can never contribute intrinsic size or
|
||||
reflow the row. Without that, the row would briefly grow as the
|
||||
image's natural dimensions arrived, then snap back on
|
||||
`object-fit: contain`. The load itself is fire-and-forget: the
|
||||
dashboard doesn't pre-check whether the agent is reachable, it
|
||||
just lets the `<img>` try and listens for an `error` event. On
|
||||
failure the handler swaps the `src` to `/favicon.svg` (served by
|
||||
the dashboard itself, always reachable) and adds the
|
||||
`icon-unreachable` class for the dimmed look. When the container
|
||||
is known stopped up front (`ContainerView.running = false`) the
|
||||
fallback fires immediately, skipping the doomed `<url>/icon`
|
||||
fetch entirely.
|
||||
|
||||
- Line 1: agent name (link → new tab), m1nd/ag3nt chip, an
|
||||
**icon-only nav strip** populated async from the agent backend
|
||||
(`📊 stats`, `🖥 screen` when GUI is enabled, `⬡ forge profile`,
|
||||
|
|
@ -440,6 +457,21 @@ body sits to the right with three stacked lines
|
|||
row tint AND draws a **rotating amber ring** around the agent
|
||||
icon, so it's obvious at a glance which container is actually
|
||||
moving.
|
||||
**Pending-state derivation:** the pill is sourced from two
|
||||
separate stores in priority order. (1) The operator-initiated
|
||||
**transient** (`transientsState`) is set on the dashboard the
|
||||
moment the operator clicks start / stop / restart / rebuild /
|
||||
destroy / spawn — covers the create-and-start window where the
|
||||
container literally isn't up yet, before any backend state event
|
||||
has fired. (2) If no transient is set, the **rebuild-queue
|
||||
entry** for this agent is consulted (`rebuildQueueState`); this
|
||||
covers worker-driven ops — meta-update cascades, crash-recover
|
||||
rebuilds, approval-driven rebuilds — that the operator didn't
|
||||
click. `ContainerStateChanged` carries neither signal, so the
|
||||
dashboard reads from the two snapshots directly. The
|
||||
`opRunning` flag (driving the `pending-running` row class +
|
||||
spinner) is true when (1) is set OR (2) is in `running` state;
|
||||
queued entries leave `opRunning` false.
|
||||
Container name + port, and a `ctx · Nk` chip showing the
|
||||
agent's last-turn context size (from `ContainerView.ctx_tokens`,
|
||||
read from the turn-stats sqlite on each `build_all` sweep;
|
||||
|
|
|
|||
Loading…
Reference in a new issue