Repository navigation
Description
Summary
In the TUI question prompt (the multiple-choice UI the agent uses to ask the user questions, very common in plan mode), trying to mouse-drag to select option text ends up submitting the option as the answer rather than copying the selected text to the clipboard.
Steps to reproduce
- Run
opencodein the terminal. - Enter plan mode (or any flow where the agent uses the
questiontool). - When the agent asks a question with several options, click and drag across the text of one of the options to select it.
- Release the mouse.
Expected: The selected text is copied to the clipboard (matching the "drag to select, release to copy" behavior used elsewhere in the TUI), and a toast confirms the copy.
Actual: The option under the mouse-up is selected/submitted, the prompt closes, and nothing is copied.
Root cause
The "copy on select" behavior is wired up at the app root in packages/opencode/src/cli/cmd/tui/app.tsx (onMouseUp → Selection.copy(renderer, toast)). Other clickable surfaces in the TUI guard their click handlers with:
if (renderer.getSelection()?.getSelectedText()) return…so that a drag-release that produced a text selection does not also fire the click action. Examples:
routes/session/index.tsx:1148(UserMessage)routes/session/index.tsx:1696(InlineTool)routes/session/index.tsx:1766(BlockTool)ui/dialog.tsx:30,ui/dialog.tsx:81
The question prompt component does not have this guard. The relevant onMouseUp handlers live in packages/opencode/src/cli/cmd/tui/routes/session/question.tsx:
- Tabs:
question.tsx:282,question.tsx:307—onMouseUp={() => selectTab(...)} - Option rows:
question.tsx:331—onMouseUp={() => selectOption()} - "Type your own answer" row:
question.tsx:360—onMouseUp={() => selectOption()}
For a single-select question (the typical plan-mode shape), selectOption() calls pick(opt.label) (question.tsx:120) which immediately submits the answer via sdk.client.question.reply(...) and tears down the prompt — beating / cancelling the root-level copy-on-select.
Proposed fix
Add the existing guard idiom to the four onMouseUp handlers in question.tsx:
const renderer = useRenderer()
// ...
onMouseUp={() => {
if (renderer.getSelection()?.getSelectedText()) return
selectOption() // or selectTab(index()), etc.
}}This is fully consistent with the pattern already used across routes/session/index.tsx and ui/dialog.tsx. After the fix:
- Click (no drag) → no selected text → option is selected as before.
- Drag to select → selection exists at mouse-up → guard returns early → root-level
onMouseUprunsSelection.copy(renderer, toast)→ text is copied and toast appears.
Happy to send a PR with this change.
Environment
- OpenCode TUI (Bun/SolidJS via
@opentui/solid) - Affected especially in plan mode (which uses the same
QuestionPromptcomponent,routes/session/index.tsx:1178)
Activity