docs/solutions/logic-errors/2026-03-29-table-arrow-navigation-must-own-moveline-and-visual-line-boundaries.md
Plain ArrowUp and ArrowDown table navigation had two related failures.
This showed up both in structural multi-block cells and in single-block cells with soft breaks or browser wrapping.
The table plugin was not fully owning plain vertical arrow movement at the moveLine seam.
That left two gaps:
So the transform knew too little about timing and too little about visual layout.
Handle collapsed table-cell ArrowUp and ArrowDown directly in withTable.moveLine(...), and only move across cells when the caret is truly at the visual edge of the current cell.
withTable.moveLine(...) for collapsed selections inside table cells.moveSelectionFromCell(...) only after the caret reaches the visual first line for ArrowUp or the visual last line for ArrowDown.true when table code handles the movement so the shared React keydown handler prevents browser default motion.The implementation lives in withTable.ts.
The browser already knows how to move a caret between visual lines inside one DOM block. The table plugin only needs to take over once that native move is exhausted.
Owning the moveLine seam removes the transient flash because the browser default move never gets a chance to paint first. Checking DOM rects removes the early cross-cell jump because the transform can finally see visual line boundaries that Slate paths cannot represent.