TT-7579 - #516
Conversation
Why it’s hard to reproduce: the grid virtualizes rows (TT-6986). pageSize was measured once. After paste/save the first paint is a short table (no spacers yet). If that measure sees only a few rows of height, pageSize sticks at ~5 and later sections never mount. On a layout where the inner pane is already the full viewport, the first measure is large enough and everything shows. A second failure mode: AppLayout is also overflow: auto. If that parent is what actually scrolls, the sheet kept curTop at 1, so scrolling through the blank padding never brought in sections 3–7. Fix: measure how many rows fit in the visible window, not the short first table; grow the window if unmounted rows are sitting in view as padding; listen to ancestor scroll (capture) so the window moves when AppLayout scrolls.
simplify
There was a problem hiding this comment.
Pull request overview
This PR addresses hard-to-reproduce PlanSheet virtualization failures caused by early/incorrect viewport measurement and by ancestor scrolling (e.g., AppLayout scrolling instead of the sheet), which could prevent later sections from mounting.
Changes:
- Extracts and centralizes sheet windowing + viewport math into a reusable
sheetWindowmodule. - Computes
pageSizebased on the visible clip (accounting for clipping/scrolling ancestors) rather than the initial short table paint. - Listens to ancestor scroll via capture, adds a
ResizeObserver, and adjusts scroll/top padding behavior so the mounted window advances correctly.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| src/renderer/src/components/Sheet/sheetWindow.ts | New shared utilities for windowing, clip measurement, and scroll-target detection used by the virtualized sheet. |
| src/renderer/src/components/Sheet/sheetWindow.test.ts | Unit tests covering window sizing, clip calculations, and scroll-target detection. |
| src/renderer/src/components/Sheet/PlanSheet.tsx | Integrates the new window/clip helpers to fix initial measurement and ancestor-scroll virtualization edge cases. |
Suppressed comments (1)
src/renderer/src/components/Sheet/PlanSheet.tsx:1351
sheetClip()can returnnull(by type), but this effect usesclip.scrollTopandclip.getBoundingClientRect()without a null check. Sincescrolleris already validated as non-null, defaultcliptoscrollerto satisfy strict null checks and avoid potential runtime issues ifsheetClip()ever returns null.
const clip = sheetClip();
const pad = topPadElRef.current;
const floor = scrollTopFloorForPad(
clip.scrollTop,
clip.getBoundingClientRect().top,
pad?.getBoundingClientRect().bottom ?? 0,
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
gtryus
left a comment
There was a problem hiding this comment.
Well, this window logic looks more complicated to me and I can't claim I understood this code like I did the code that used to be there. But hopefully AI got it right.
Why it’s hard to reproduce: the grid virtualizes rows (TT-6986). pageSize was measured once. After paste/save the first paint is a short table (no spacers yet). If that measure sees only a few rows of height, pageSize sticks at ~5 and later sections never mount. On a layout where the inner pane is already the full viewport, the first measure is large enough and everything shows.
A second failure mode: AppLayout is also overflow: auto. If that parent is what actually scrolls, the sheet kept curTop at 1, so scrolling through the blank padding never brought in sections 3–7.
Fix: measure how many rows fit in the visible window, not the short first table; grow the window if unmounted rows are sitting in view as padding; listen to ancestor scroll (capture) so the window moves when AppLayout scrolls.