docs: scrub module-split cookies from tabs.js + migrate paintAtomic rationale (#712 batch 2)
Two threads cleaned up in tabs.js: 1. Top-of-file '#406 step 1/2/3' historical narrative deleted — it documented past module splits (moves to common.js / flow.js, file rename app.js → tabs.js) which are git-history concerns, not current-behaviour docs. Replaced with a two-sentence contract description that references docs/web-ui.md and the present-tense module split. 2. Five 'moved to ./common.js (#406)' stubs deleted — same reasoning. The imports at the top of the file already document what's in common.js; standalone 'this function lives elsewhere' pointers are noise once you stop tracking the move event. paintAtomic's substantive rationale migrated to a new 'Atomic section repaint' subsection in docs/web-ui.md (under the existing focus-preservation note); in-code comment shrinks to a two-line reference. Same pattern as the topology-tree batch. Net: 36 fewer lines in tabs.js, 14 new in docs/web-ui.md. Functional code unchanged; build clean. refs #712
This commit is contained in:
parent
0a98327685
commit
711d42031c
2 changed files with 25 additions and 36 deletions
|
|
@ -86,6 +86,20 @@ and, if so, skips the refresh (defers 2s). The operator never has
|
|||
the form yanked out from under them mid-type; the update lands as
|
||||
soon as they blur.
|
||||
|
||||
**Atomic section repaint:** every managed-section renderer goes
|
||||
through `paintAtomic(liveRoot, build)`: the builder appends into
|
||||
a fresh `DocumentFragment` (off-DOM) and the commit is one
|
||||
`replaceChildren` call. The naive `root.innerHTML = ''; root.append(...)`
|
||||
shape was visibly flashing empty on every poll cycle — on async
|
||||
paths the await yield gave the browser a paint opportunity between
|
||||
the clear and the re-append, and on complex builds (many `el()`
|
||||
allocations) layout could escape the per-task budget even on the
|
||||
synchronous path. The fragment approach keeps the intermediate
|
||||
empty state invisible. Builders receive the fragment as their
|
||||
`root`, so existing renderer code carries over unchanged; early
|
||||
returns inside the builder still commit whatever was appended
|
||||
before they returned.
|
||||
|
||||
**`<details>` open-state preservation:** any collapsible element
|
||||
tagged with `data-restore-key="<stable-key>"` survives the
|
||||
refresh. `snapshotOpenDetails()` walks managed sections before
|
||||
|
|
|
|||
|
|
@ -1,18 +1,14 @@
|
|||
// /index.html entry point: tab renderers + tab routing + refreshState
|
||||
// + notification deltas. Reads /api/state on cold load and after every
|
||||
// async-form submit; live updates run through `applyXxx` mutation
|
||||
// handlers triggered by the dashboard event stream.
|
||||
// handlers triggered by the dashboard event stream (subscribed via
|
||||
// `openStream` from common.js). See docs/web-ui.md::Shape (shared by
|
||||
// both) for the broader contract.
|
||||
//
|
||||
// #406 step 1: pure helpers + side panel + OS notifications + path
|
||||
// linkification moved to `./common.js`.
|
||||
// #406 step 2: the flow-only IIFEs (operator inbox, inbox-pill, broker
|
||||
// terminal, @-mention composer) moved to `./flow.js`. /flow.html loads
|
||||
// `flow.js` as its own bundle entry; this file is loaded only by
|
||||
// /index.html.
|
||||
// #406 step 3: file renamed from `app.js` → `tabs.js` since it owns
|
||||
// the dashboard *tabs* surface only (the FL0W page has its own bundle).
|
||||
// Live SSE subscription is wired through `openStream` from common.js
|
||||
// (#406 step 3 hookup; see also #408 for stream-side filtering).
|
||||
// Pure helpers (DOM, side panel, OS notifications, path linkification)
|
||||
// live in `./common.js`; the flow-page surface (operator inbox, broker
|
||||
// terminal, @-mention composer) lives in `./flow.js` — `flow.html` and
|
||||
// `index.html` each load their own bundle.
|
||||
|
||||
import { marked } from 'marked';
|
||||
import {
|
||||
|
|
@ -41,37 +37,16 @@ window.marked = marked;
|
|||
const CTX_WARN_TOKENS = 150_000; // fallback red threshold (≈ 75% of 200k)
|
||||
const CTX_CAUTION_TOKENS = 100_000; // fallback yellow threshold (≈ 50% of 200k)
|
||||
|
||||
// Helpers ($, el, esc, form, fmtAgeSecs) moved to ./common.js (#406).
|
||||
|
||||
// #464 — atomic-swap render helper. Each managed section's render
|
||||
// function used to do `root.innerHTML = ''; root.append(...);` in
|
||||
// sequence; even though both operations sit in the same JS turn,
|
||||
// operators could still see a "blink" on every poll cycle because
|
||||
// (a) on async paths the await yield gave the browser a paint
|
||||
// opportunity, and (b) complex builds with many `el()` allocations
|
||||
// can blow the browser's per-task budget enough for layout to flash
|
||||
// empty before the new children land.
|
||||
//
|
||||
// The fix: build the new content off-DOM into a `DocumentFragment`,
|
||||
// then move it into the live root in a single `replaceChildren`
|
||||
// call. The browser never sees an intermediate empty state. Builder
|
||||
// callbacks receive the fragment as their `root` argument, so each
|
||||
// renderer's existing `root.append(...)` code carries over with
|
||||
// zero internal changes. Early-return inside the builder is fine —
|
||||
// the commit still happens with whatever the builder appended.
|
||||
// Atomic-swap render helper: build into a DocumentFragment off-DOM,
|
||||
// commit with one `replaceChildren`. See docs/web-ui.md::Atomic
|
||||
// section repaint for why (no intermediate empty-state flash on
|
||||
// poll cycles even when the builder allocates a lot of `el()`).
|
||||
function paintAtomic(liveRoot, build) {
|
||||
const buf = document.createDocumentFragment();
|
||||
build(buf);
|
||||
liveRoot.replaceChildren(buf);
|
||||
}
|
||||
|
||||
// Side panel singleton (Panel) moved to ./common.js (#406).
|
||||
|
||||
// Path linkification + file-preview side panel (openFilePanel,
|
||||
// makePathLink, appendText, appendLinkified) moved to ./common.js (#406).
|
||||
|
||||
// OS notification module (NOTIF) moved to ./common.js (#406).
|
||||
|
||||
// Track which items we've already notified about so a re-render
|
||||
// doesn't re-fire for the same row. Keyed by stable ids; reset only
|
||||
// when the page reloads.
|
||||
|
|
|
|||
Loading…
Reference in a new issue