anomalyco / anomalyco/opencode

Dialog opened from an onMouseDown handler closes immediately (same click's mouseup hits the backdrop)

Open
#46,982 0 comments 0 reactions 1 assignee View on GitHub

@simonklee is already working on this.

Since Sep 3, 2026.

Dominant language
TypeScript
Stars
209k
Forks
27.5k
PR merge metrics
PR metrics pending

Description

Description

Plugins that open a dialog from an onMouseDown handler get a dialog that flashes and closes instantly — the release of the same physical click dismisses it.

packages/tui/src/ui/dialog.tsx closes the full-screen backdrop on onMouseUp (onMouseDown only sets the selection dismiss flag). OpenTUI dispatches press/release as separate events and hit-tests each fresh, and the dialog mounts synchronously during the press — so the release hit-tests against the newly mounted backdrop and onClose() fires before the user can interact. There is no opt-out (dismissOnOutsideClick or similar) on Dialog / DialogSelect / dialog.replace.

Workaround: open the dialog from onMouseUp instead — works, but any element that legitimately needs to react on press can't open dialogs safely.

Steps to reproduce
  1. Load a plugin that registers a bottom-bar slot and opens a dialog on press:
export const Repro = {
  id: "repro-dialog",
  tui(api) {
    api.slots.register("app_bottom", () => (
      <box onMouseDown={() => {
        const DialogSelect = api.ui.DialogSelect
        api.ui.dialog.replace(() => (
          <DialogSelect
            title="Pick one"
            options={[{ title: "A", value: "a" }, { title: "B", value: "b" }]}
            onSelect={() => api.ui.dialog.clear()}
          />
        ))
      }}>
        <text>click me</text>
      </box>
    ))
  },
}
  1. Start opencode, click the bar element once.
  2. The dialog appears for a frame and closes by itself.

Changing the handler to onMouseUp makes the dialog stay open — confirming it's the same click's release hitting the freshly mounted backdrop.

Suggested fix
  • Ignore backdrop mouseups belonging to the press that opened the dialog (e.g. record when the stack becomes non-empty and drop the first mouseup of that sequence), or
  • add a dismissOnOutsideClick opt-out on Dialog / DialogSelect for plugin use.

Happy to test a fix.

Environment
  • OpenCode: 1.18.26 (npm)
  • OS: Windows 11
  • Terminal: Windows Terminal
  • Plugins: FlashCodersRead (TUI speed-reader bar — where I hit this)

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.