fix(cursor): z-stacking suppression for occluded cursors (A24)#86
Conversation
…#83) Cursor declarations now follow z-stacking: at finalize time, hit-test the declared cell. If the topmost painted element isn't the declared node or a descendant, suppress the cursor instead of parking it. Modals over TextInputs no longer leak the input's caret through the modal frame. Helper extracted to cursor-visibility.ts for testability. Co-Authored-By: Mark <psyhik17@gmail.com> Co-Authored-By: Claude <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 4a6527d101
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| const hit = hitTest(root, col, row) | ||
| if (hit === null) return false | ||
| return isDescendantOrSelf(hit, declaredNode) |
There was a problem hiding this comment.
Don't treat layout-only boxes as cursor occluders
When a higher-z absolute Box is used only as a positioning/layout wrapper (no backgroundColor, opaque, border, or child at this cell), it does not actually write any terminal cells over the focused input, but hitTest still returns that Box because the point is inside its layout rect. This makes the new visibility check hide the TextInput cursor even though the underlying input remains visible; for example, an empty transparent overlay wrapper covering the screen will suppress every cursor below it. The occlusion test needs to account for what painted the cell, not just which layout rect contains it.
Useful? React with 👍 / 👎.
…verlays (codex review on #86)
Closes #83 (A24).
What
Cursor declarations now follow z-stacking. At finalize time in `ink.tsx`, hit-test the declared screen cell. If the topmost painted element isn't the declared node or a descendant of it, suppress the cursor — something else paints on top.
Symptom this fixes: a background ``'s bar/block cursor renders through any modal-shaped Box on top, even though the modal occludes the cell visually. Per Mark's repro at #83, the cursor visibly bleeds inside the modal frame.
How
Modal-over-input that DOES contain a focused TextInput: the inner input's `useDeclaredCursor` wins last-write-wins; hit-test at the cursor cell returns the inner input (descendant of the modal), which IS the declared node — so the cursor parks correctly inside the modal. No regression.
Tests
11 new tests in `cursor-visibility.test.ts`:
728 tests passing (was 717; +11). typecheck / lint / build clean.
Out of scope (future)