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:
iris 2026-05-31 11:51:17 +02:00 committed by Mara
commit 711d42031c
2 changed files with 25 additions and 36 deletions

View file

@ -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