Skip to content

fix(live): keep legend toggle above VCR bar - #84

Merged
dborup merged 3 commits into
masterfrom
codex/port-upstream-2049-live-toggle-anchor
Sep 25, 2026
Merged

dborup merged 3 commits into
masterfrom
codex/port-upstream-2049-live-toggle-anchor

Conversation

@adminopenclaw8-sketch

@adminopenclaw8-sketch adminopenclaw8-sketch commented Sep 23, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

Fork-adapted port of Kpa-clawbot/CoreScope#2049.

  • anchor the Live legend and feed-show buttons to .live-page, the same containing block as the VCR bar
  • prevent the mobile bottom-navigation reserve from moving the buttons underneath the VCR bar at 641–768 px
  • register the existing anchor regression test and add a real Playwright hit-test at tablet and desktop widths

Why

The buttons were position: fixed, while .vcr-bar is absolutely positioned inside the shorter .live-page. At tablet widths the two coordinate systems differ by --bottom-nav-reserve; the VCR bar then covers the legend toggle and consumes pointer events.

The production change is constant-time CSS positioning only. It adds no runtime loop, API call, dependency, configuration value, or customizer setting.

Validation

Fresh on commit 21c6c774d0e110129f2b242ea7c1aa6d4579632e:

  • node test-issue-1107-live-layout.js — 16 passed
  • node test-issue-1833-legend-toggle-vcr-offset.js — 5 passed
  • node scripts/check-css-vars.js — passed
  • Playwright test-issue-1833-legend-toggle-clickable-e2e.js against a local Go server — 4 passed at 720 px and 1440 px, including real pointer clicks
  • go test ./... in cmd/server — passed
  • go test ./... in cmd/ingestor — passed
  • workflow YAML parse and git diff --check — passed

Browser validation used a migrated temporary copy of test-fixtures/e2e-fixture.db; the checked-in fixture was not modified. The test server was shut down afterward.

Baseline note

npm test reaches test-frontend-helpers.js and reports two pre-existing favStar assertion failures (705 passed, 2 failed). The same two failures reproduce on a clean worktree at base 6334c42789bd15b7887f56ffc88446f803ef42c6. They are unrelated to this PR; this PR does not modify nodes.js or those assertions.

No deploy, release, dependency, cache-buster, or customizer changes.

Master sync (21c6c774 → ce496a4e)

A separate independent feature-review of 21c6c774 gave PASS, no blockers before this sync. Master had since moved ~38 commits ahead (through issue #86, #88, #89, #91), so this branch was brought up to date with an ordinary merge commit — no rebase, no squash, no amend.

  • Old head: 21c6c774d0e110129f2b242ea7c1aa6d4579632e
  • New head (merge commit): ce496a4e52904eb00676c926968c278cbccd982d
  • Parents: 21c6c774… (this branch) + 4c5efa7b75efa46c0696286a8f800b68bb9935f9 (master at sync time)
  • Merge tree: 563ca69966d8540bf4fc5ecbb06885bb8b41dff8, computed conflict-free with git merge-tree before touching any ref and confirmed identical to the actual merge commit's tree.

Filescope, verified byte-for-byte:

  • This PR's own files (public/live.css, test-issue-1107-live-layout.js, both test-issue-1833-* files) are byte-identical before and after the sync.
  • public/live.js and test-live-multibyte-only-e2e.js (issue fix(live): restore the Multibyte only toggle before init awaits #88's reload-race fix) are byte-identical to current master.
  • Every other newer-master file checked (topology/blacklist privacy filter, relay-airtime share, reach-rank, QA scripts, etc.) is byte-identical to master — the merge did not touch anything it didn't need to.
  • .github/workflows/deploy.yml and test-all.sh are the only two files both sides touched; the diff against master is purely the two additive lines this PR already had (its own test registrations) layered next to master's newer ones. No trigger, permission, job, needs, or fork-guard changed — verified by a full diff against master (additive-only) and by TestForkGuardOnSideEffectJobs, TestForkGuardOnPublishSteps, TestForkGuardLeavesTestJobsRunning, TestReleaseFastPathWorkflowExists, TestDeployWorkflowNoLongerTriggersOnTags, all passing on the merge result.

Fresh verification on an isolated git archive export of the merge result (not the branch tip alone):

  • git diff --check, node --check on every changed/relevant Live JS file, YAML-parse of all six workflow files — all clean.
  • test-issue-1833-legend-toggle-vcr-offset.js × 10 and test-issue-1107-live-layout.js × 10 — 10/10 clean.
  • test-issue-1833-legend-toggle-clickable-e2e.js × 5 — 5/5 clean (4 passed, 0 failed each run).
  • test-live-multibyte-only-e2e.js (master's fix(live): restore the Multibyte only toggle before init awaits #88 test) × 5 — 5/5 clean (10/10 assertions each run), including its toggle-before-init and real-reload-persistence checks.
  • test-reach-rank-e2e.js (Back/Forward SPA-navigation control) × 3 — 14/14 clean each run.
  • test-issue-1206-vcr-overlap-e2e.js, test-issue-1244-live-vcr-row-hints-e2e.js, test-issue-1510-live-nav-pin-e2e.js, test-live-fullscreen-1572-e2e.js, test-live-vcr-mode-contrast.js — all clean.
  • A dedicated navigate-away-and-back-to-Live probe × 5 — no overlap, real click works, no console errors, every run.
  • Browser matrix (real Playwright/Chromium, isolated local server, migrated temp copy of the fixture) at 1920×1080, 1440×900, 1024×768, 768×1024, 768×900, 700×900, 641×900, 812×375, 720×420, 390×844: no VCR-bar overlap, elementFromPoint hits the button, real click and keyboard Enter both toggle state, no horizontal overflow, no console errors, unaffected by many/long legend entries, and (390×844) the button is genuinely hidden (not just visually) and does not intercept pointer events at its would-be location. 720×300 — see residual risk below.
  • Mutation: reverted both position: absolute declarations to fixed in a scratch copy. Both unit tests and the real Playwright hit-test failed on exactly the intended assertion — the E2E failure reproduced the real symptom verbatim (<canvas id="vcrLcdCanvas"> from <div id="vcrBar"> intercepting the click). Reverted before finishing; never committed.
  • Independently re-verified end to end by a separate reviewer agent (merge mechanics, the residual-risk repro below, and a mutation/viewport spot-check), which concurred this sync is safe to push.

#feedShowBtn under .top-nav at short heights — investigated and fixed (commit f2dd3f0b)

The residual risk noted above (feed-show button landing under .top-nav at short viewport heights, e.g. 720×300) was flagged at master-sync time as unclassified. It has since been definitively root-caused with a controlled A/B/C comparison and fixed in this PR.

Classification: this was a regression introduced by this PR's own position: fixed → absolute change, not a pre-existing bug. A/B/C test — identical fixture data, identical Playwright flow ("hide feed, then click show"), three git trees (current master, this PR's original feature-head 21c6c774, and the master-integrated head ce496a4e), 10-viewport matrix (720×250/275/300/320/375/420, 641/700/768×300, 812×375) with 720×300 repeated 10× to rule out timing flakes:

  • master: 18/19 pass. The one exception (720×250) is a separate, pre-existing edge case unrelated to .top-nav (button center hit-tests to itself, no nav overlap — the click simply times out at an extremely cramped 250px height); it reproduces identically on the fixed code below, so it is not part of this regression's scope.
  • 21c6c774 (original feature-head) and ce496a4e (master-integrated head): both fail ~16/19 cases, all with the same signature — #feedShowBtn overlaps .top-nav by 12–39px and elementFromPoint at the button's center resolves to the nav, not the button.

Fix: .feed-show-btn keeps position: absolute (unchanged from this PR's own .legend-toggle-btn fix, and deliberately not reverted to position: fixed — an earlier attempt at exactly that was empirically found to reintroduce a different bug: at 641px width and normal (900px) height, a fixed-positioned #feedShowBtn collides with the still-absolute #legendToggleBtn because the two positioning schemes drift apart under --bottom-nav-reserve, the same containing-block mismatch this PR's own legend fix exists to avoid). Instead, #feedShowBtn's total bottom offset is now clamped so it can never rise closer than .top-nav's own height to .live-page's top edge, regardless of viewport height; the clamp only ever pulls the offset down from its existing VCR-bar-clearing value, so it cannot reintroduce the VCR-bar overlap this PR already fixes for the legend toggle.

New regression test (added to the existing test-issue-1833-legend-toggle-clickable-e2e.js, not a new file): a 720×300 case asserting geometric non-overlap with .top-nav, a real elementFromPoint hit-test at the button's center, and the actual functional consequence of a real Playwright click (#liveFeed's hidden state actually toggling) — not just CSS inspection.

Verification:

  • Full required viewport matrix: 18/19 pass on the fix (matching master's own ceiling exactly, including reproducing master's same unrelated 720×250 edge case).
  • 641–768px width band re-checked at both short (300px) and normal (900px) height: no VCR-bar overlap, no collision between #feedShowBtn and #legendToggleBtn.
  • SPA navigate-away-and-back remount at 720×300: click still works, no nav overlap.
  • Keyboard: Tab-equivalent focus + Enter and + Space both correctly toggle the feed.
  • All four corners of the button (not just center) hit-test to itself; no horizontal overflow; zero console errors across all runs.
  • test-issue-1833-legend-toggle-clickable-e2e.js × 13, test-issue-1833-legend-toggle-vcr-offset.js × 5, test-live-multibyte-only-e2e.js (fix(live): restore the Multibyte only toggle before init awaits #88) × 5, test-issue-1107-live-layout.js, test-issue-1206-vcr-overlap-e2e.js, test-issue-1205-live-controls-anchor-e2e.js, test-issue-1244-live-vcr-row-hints-e2e.js, test-issue-1510-live-nav-pin-e2e.js, test-issue-1532-live-fullscreen.js, test-issue-1413-nav-overlap-e2e.js, test-live.js — all clean.
  • 4 mutation tests confirm the new assertions actually catch the bug class: (1) reverting to the original unclamped offset → red with the exact original overlap signature; (2) reverting .legend-toggle-btn to position: fixed → red with the original VCR-bar overlap; (3) raising only #feedShowBtn's z-index without fixing its position → still red (geometric overlap assertion, not fooled by a z-index-only non-fix); (4) a broken click handler with geometry left untouched → hit-test-only assertions would pass (false negative), but the real functional-state assertion correctly fails, demonstrating hit-testing alone is not sufficient and the functional check is load-bearing.
  • Independently re-reviewed end to end by a separate reviewer agent (diff scope, the clamp math against .live-page's actual containing-block behavior, an independent empirical spot-check at 720×300 and 700×900, and the mutation tests' structural validity) — verdict: PASS, no blockers.
  • git diff --check clean; favStar remains the only (pre-existing, unrelated, confirmed reproducing identically on unmodified ce496a4e) failure in test-frontend-helpers.js.

No deploy, staging, or production contact was made at any point in this fix.

Openclaw and others added 3 commits September 23, 2026 15:59
Kpa-clawbot#1833 round 2 anchored both .feed-show-btn and .legend-toggle-btn to
.live-page via position:absolute so a viewport-fixed anchor could no
longer drift out of sync with the VCR bar at 641-768px width. That
change also introduced a new regression: .feed-show-btn's offset
(stacked above .legend-toggle-btn) can rise far enough at short
viewport heights to land underneath .top-nav, since .live-page sits
flush with the viewport top on /live with .top-nav fixed on top of it
rather than pushing it down. A real click on the button then does
nothing, and the feed panel can never be un-hidden again at those
sizes.

A/B/C testing (master, PR #84's original feature-head, and the
current master-integrated head, identical fixture + Playwright flow,
10-viewport matrix with 720x300 repeated 10x) confirmed this is a
regression introduced by #84, not pre-existing: master passes 19/19
required cases; both #84-derived trees fail ~16/19 with the button
geometrically overlapping and hit-testing under .top-nav.

Fix: clamp .feed-show-btn's total bottom offset so it can never rise
closer than .top-nav's height to .live-page's own top edge, while
keeping position:absolute (matching .legend-toggle-btn, avoiding the
fixed/absolute containing-block mismatch that an earlier attempt at
this fix — reverting only .feed-show-btn to position:fixed — was
empirically found to reintroduce as a different collision with
.legend-toggle-btn at 641px width). The clamp only ever pulls the
offset down from its existing VCR-bar-clearing value, so it cannot
reintroduce the VCR-bar overlap Kpa-clawbot#1833 round 2 already prevents.

Adds a regression test to the existing #84 E2E file covering the
720x300 case: real hit-test against .top-nav, and a real click
verified against the actual liveFeed hidden-state change (not just
CSS). Verified clean across the full required viewport matrix, the
641-768px width band at both short and normal heights (no collision
with .legend-toggle-btn or #vcrBar), an SPA remount, keyboard
Enter/Space activation, and all four corner hit-tests. Confirmed via
4 mutation tests that the new assertions actually catch: the original
unclamped offset, legend-toggle reverted to fixed, a z-index-only
non-fix, and a broken click handler that passes hit-testing alone.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@dborup
dborup merged commit bd9dfa9 into master Sep 25, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants