Skip to content

TUI: Dragging to select text on a question option submits the option instead of copying to clipboard #24986

Closed

Description

@nikhil-patel-whatnot

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

  1. Run opencode in the terminal.
  2. Enter plan mode (or any flow where the agent uses the question tool).
  3. When the agent asks a question with several options, click and drag across the text of one of the options to select it.
  4. 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 onMouseUp runs Selection.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 QuestionPrompt component, routes/session/index.tsx:1178)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions