-
Notifications
You must be signed in to change notification settings - Fork 278
Open
Labels
bugSomething isn't workingSomething isn't workingcoreThis relates to the core packageThis relates to the core package
Description
When a scrollbox contains content taller than its visible area, clicks outside the scrollbox's visible bounds are incorrectly captured by the scrollbox. The content is visually clipped correctly, but hit-testing uses the full unclipped content height.
- When scrolled to top: clicking below the dialog hits the scrollbox
- When scrolled to bottom: clicking above the dialog hits the scrollbox
Steps to Reproduce
- Create a dialog with an overlay (for click-to-close)
- Add a scrollbox inside the dialog with content taller than the visible area (e.g., 50 lines)
- Open the dialog
- Click directly below the scrollable content (in the overlay area)
Expected: The overlay receives the click and the dialog closes
Actual: The scrollbox receives the click (even though it's visually contained within the dialog)
Minimal Example
import { render, useKeyboard, useTerminalDimensions, useRenderer } from "@opentui/solid"
import { createSignal, Show, For } from "solid-js"
function App() {
const [showDialog, setShowDialog] = createSignal(false)
const [lastClick, setLastClick] = createSignal("none")
const dimensions = useTerminalDimensions()
const renderer = useRenderer()
useKeyboard((key) => {
if (key.name === "q") {
renderer.destroy()
process.exit(0)
}
if (key.name === "d") setShowDialog(!showDialog())
if (key.name === "escape") setShowDialog(false)
})
const lines = Array.from({ length: 50 }, (_, i) => `Line ${i + 1}: This is some content`)
return (
<box flexDirection="column" height={dimensions().height} width={dimensions().width} backgroundColor="#1a1a2e">
<text>Press 'd' to toggle dialog, 'q' to quit, 'esc' to close</text>
<text>Last click: {lastClick()}</text>
<Show when={showDialog()}>
{/* Overlay - clicking here should close the dialog */}
<box
position="absolute"
top={0}
left={0}
width={dimensions().width}
height={dimensions().height}
backgroundColor="#ff000033"
onMouseDown={() => {
setLastClick("OVERLAY (red)")
setShowDialog(false)
}}
>
<box
position="absolute"
top={Math.floor(dimensions().height / 4)}
left={Math.floor(dimensions().width / 4)}
width={Math.floor(dimensions().width / 2)}
height={Math.floor(dimensions().height / 2)}
backgroundColor="#0000ff"
borderStyle="rounded"
flexDirection="column"
onMouseDown={(e: { stopPropagation: () => void }) => {
console.log(">>> DIALOG BOX clicked")
setLastClick("DIALOG BOX (blue)")
e.stopPropagation()
}}
>
<scrollbox
flexGrow={1}
backgroundColor="#ffff00"
onMouseDown={(e: { stopPropagation: () => void }) => {
setLastClick("SCROLLBOX (yellow)")
e.stopPropagation()
}}
>
<For each={lines}>{(line) => <text>{line}</text>}</For>
</scrollbox>
</box>
</box>
</Show>
</box>
)
}
render(() => <App />)- Press
dto open the dialog - Click in the red area directly below the scrollable content in the dialog box
- "Last click" shows "SCROLLBOX (yellow)" instead of "OVERLAY (red)" and closing the dialog
Environment
- @opentui/core: 0.1.68
- @opentui/solid: 0.1.68
- bun: 1.3.5
- OS: Linux x64
- Terminal: Tested in Ghostty and the Zen integrated terminal
kommander
Metadata
Metadata
Assignees
Labels
bugSomething isn't workingSomething isn't workingcoreThis relates to the core packageThis relates to the core package