Note: this bug was diagnosed, reduced, and filed by an AI agent (Claude Code), with human review and approval before submission.
Summary
A box with border + fixed height + overflow="hidden" registers no hit-grid zone for its last content row. The row renders correctly, but onMouseDown on it never fires — clicks pass through to whatever is behind. Removing overflow="hidden" (nothing else) makes every row clickable.
Verified on @opentui/core + @opentui/solid 0.1.90 and 0.1.107 (macOS, bun).
Repro
Self-contained script using testRender — no terminal needed, bun run repro.tsx:
import { testRender } from "@opentui/solid";
const clicks: string[] = [];
function Row(p: { label: string }) {
return (
<box flexDirection="column" flexShrink={0} onMouseDown={() => clicks.push(p.label)}>
<box flexDirection="row">
<text>{p.label}</text>
</box>
</box>
);
}
function App() {
return (
<box flexDirection="column" flexGrow={1}>
<box flexGrow={1} />
{/* overflow="hidden" is the trigger: remove it and row3 becomes clickable */}
<box border borderStyle="rounded" flexShrink={0} height={6} overflow="hidden">
<box flexDirection="column">
<box flexDirection="row" paddingLeft={1} onMouseDown={() => clicks.push("name")}>
<text>session-name</text>
</box>
<box flexDirection="column" paddingLeft={1}>
<Row label="row1" />
<Row label="row2" />
<Row label="row3" />
</box>
</box>
</box>
<box flexGrow={1} />
</box>
);
}
const { renderOnce, captureCharFrame, mockMouse, mockInput } = await testRender(() => <App />, {
width: 30,
height: 14,
});
await renderOnce();
captureCharFrame().split("\n").forEach((l, i) => console.log(i, JSON.stringify(l.slice(0, 24))));
for (let y = 0; y < 12; y++) {
clicks.length = 0;
await mockMouse.click(5, y);
await renderOnce();
console.log(`click y=${y} -> ${clicks.length ? clicks.join(",") : "(nothing)"}`);
}
// Same result through the real stdin path (raw SGR, 1-based coords):
for (const [label, sgrY] of [["name", 6], ["row1", 7], ["row2", 8], ["row3", 9]] as const) {
clicks.length = 0;
mockInput.pressKey(`\x1b[<0;6;${sgrY}M`);
mockInput.pressKey(`\x1b[<0;6;${sgrY}m`);
await renderOnce();
console.log(`SGR y=${sgrY} (${label}) -> ${clicks.length ? clicks.join(",") : "(nothing)"}`);
}
process.exit(0);
Actual output (0.1.107)
4 "╭───────────────────────"
5 "│ session-name "
6 "│ row1 "
7 "│ row2 "
8 "│ row3 "
9 "╰───────────────────────"
click y=5 -> name
click y=6 -> row1
click y=7 -> row2
click y=8 -> (nothing) <- row3 renders here but has no zone
SGR y=6 (name) -> name
SGR y=7 (row1) -> row1
SGR y=8 (row2) -> row2
SGR y=9 (row3) -> (nothing)
Both the mockMouse path and the raw SGR stdin path agree: every zone is correctly aligned with its rendered row, except the last content row, which has no zone at all.
Expected
click y=8 -> row3 — the last row inside the border should be clickable like the others.
Notes
- The trigger is specifically the combination
border + fixed height + overflow="hidden". Dropping overflow="hidden" fixes hit-testing with no visual change (content already fits the fixed height).
- It always eats exactly the last content row (the one adjacent to the bottom border), regardless of row count.
- Real-world symptom that led here: the bottom row of a bordered list in a tmux sidebar was rendered but unclickable, which initially looked like an app-level state bug.
- Workaround we shipped: omit
overflow="hidden" and rely on height math for truncation.
Summary
A box with
border+ fixedheight+overflow="hidden"registers no hit-grid zone for its last content row. The row renders correctly, butonMouseDownon it never fires — clicks pass through to whatever is behind. Removingoverflow="hidden"(nothing else) makes every row clickable.Verified on
@opentui/core+@opentui/solid0.1.90 and 0.1.107 (macOS, bun).Repro
Self-contained script using
testRender— no terminal needed,bun run repro.tsx:Actual output (0.1.107)
Both the
mockMousepath and the raw SGR stdin path agree: every zone is correctly aligned with its rendered row, except the last content row, which has no zone at all.Expected
click y=8 -> row3— the last row inside the border should be clickable like the others.Notes
border+ fixedheight+overflow="hidden". Droppingoverflow="hidden"fixes hit-testing with no visual change (content already fits the fixed height).overflow="hidden"and rely on height math for truncation.