Repository navigation
feat(views): find in page reaches every row of the logs stream - #2568
Conversation
…d logs stream Rows outside the virtual window get hidden=until-found stand-ins in layers before and after the window. On a match the browser fires beforematch; the stand-in moves to its row's offset so the browser's own scroll lands there, and the found row takes the keyboard focus.
…est the before side
|
Warning Review limit reachedYou've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. Next included review available in 21 minutes. View limit details
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. |
This comment has been minimized.
This comment has been minimized.
🍁 Maple PR previewNote Preview resources were removed when this pull request closed. Final commit |
Maple review🟢 Confidence 10/10 · safe to merge. The change since the last review adds a happy-dom test of the The delta since the last review is
|
Preview check (app-pr-2568.maple.dev,
|
| Check | Result |
|---|---|
| Rendered rows + stand-ins = loaded rows | ✅ 9 rendered + 5 after = 14 (footer "14 logs") |
A text-fragment match on row 12, below the window (a fresh load with #:~:text=, the same hidden="until-found" + beforematch reveal Cmd+F uses) |
✅ the browser scrolled, row 12 rendered fully inside the scroller with data-focused="true", and its stand-in and group were un-hidden |
| Scroll back to top | ✅ row 12's stand-in and group are hidden="until-found" again, 9 + 5 = 14 |
The before layer |
✅ scrolled to the bottom: rows 5–13 rendered, stand-ins for 0–4 |
| j/k after a find | ✅ 12 → 11 → 10 → 11 |
| Density and wrap toggles | ✅ every state totals 14 (wrap off renders all 14 with no stand-ins) |
| Reload | ✅ 9 + 5 = 14 after the refetch |
| Console errors / page errors | ✅ 0 during the whole run |
| Row 12 found and focused | Scrolled away, stand-in hidden again |
|---|---|
![]() |
![]() |
Video of the run: preview-run.webm
Not covered here:
- The live Cmd+F find bar (pressing Enter to step through matches, and the count it shows). Chromium has no automation hook for it.
- A real match on a row above the window. A text fragment only fires on a fresh load, and a fresh load always starts at the top. The
beforeside is covered by the scene tests.
The 64-row grouping is covered by the 2,000-row lab benchmark in the PR description.
Traces: the change is client-only DOM work on a hot scroll path. It makes no requests and calls no backend code, so it has no spans and nothing to trace.


What
The logs stream is virtualized: only the ~35 rows on screen exist in the DOM, so the browser's find in page (Cmd+F) missed almost every log. A search for a request id in a 2,000-row stream said "0 results" while the row was in the list.
Now every row is findable:
hidden="until-found"). Stand-ins for rows above the window go in a layer before the rendered rows, rows below go after them, so the browser counts and steps through matches in list order.beforematchon the stand-in. The Mount moves the stand-in to its row's virtual offset, so the browser's own scroll-into-view lands on the row and the virtualizer renders it. The found row takes the keyboard focus, so it is marked and j/k carry on from it.hidden="until-found", so the browser skips style and layout until one matches) and memoized withcreateKeyedLazy: a window move rebuilds only the chunks at its edges. A stand-in is one element and one text node.The mechanism lives in
packages/views/src/lib/findable.ts(findableLayersfor the view,bindFindablefor the virtualizer Mount,foundAfterWindowfor the model) so the traces list and the waterfall can adopt it next.Known tradeoff (same as the approach this follows): while the found row is on screen its stand-in stays, because the browser's active match lives in it. The count reads one higher until the row scrolls away, and the next match after it skips rows already on screen.
Evidence
/lab/bench/logs(2,000 wide rows), production builds ofmainand this branch, headless Chromium.Find reach
Synthetic wide log row 1(true count 1,111)#:~:text=, the samebeforematchreveal as Cmd+F)Cost (median of 5 runs, 4x CPU throttle; the scroll is the lab harness's 121-step scroll through the whole list)
About two DOM nodes per row, and about 9% more script while scrolling (rows crossing the window edge move their stand-in between layers; chunk sizes of 16, 32 and 64 measured within 2% of each other). Frame p95 and blocking time are unchanged.
Tests
vitest run src/ui/logs(21 passed),typecheckforpackages/viewsandapps/web,oxlint -c .oxlintrc.effect.jsonclean on the changed files.Not yet verified: the live Cmd+F find bar (Enter stepping, the count it shows). It can't be driven headless; it will be checked on the preview.
🤖 Generated with Claude Code
Open in [code]smith · Need help on this PR? Tag
@codesmith-botwith what you need.