Skip to content

fix(web): make terminal selection actions reliable - #6555

Closed
Adamulek123 wants to merge 13 commits into
pingdotgg:mainfrom
Adamulek123:fix/terminal-context-menu
Closed

Adamulek123 wants to merge 13 commits into
pingdotgg:mainfrom
Adamulek123:fix/terminal-context-menu

Conversation

@Adamulek123

@Adamulek123 Adamulek123 commented Aug 14, 2026 •

Copy link
Copy Markdown
Contributor

What Changed

Terminal text could be selected but then become effectively stuck: Copy was disabled in the desktop fallback menu, Ctrl+Shift+C and Ctrl+Shift+V did nothing while the initial selection popup was open, Paste did not work, and Add to chat disappeared after dismissing the first popup. Scrolling the terminal could leave the popup inconsistent with its selection.

This makes the initial selection popup and the reopened right-click menu use the same terminal-aware actions. Both expose Add to chat, Copy, and Paste; show the platform shortcut (Ctrl+Shift+C/V on Windows and Linux, ⌘C/V on macOS); execute those shortcuts while open; dismiss on outside clicks or terminal scrolling; and can be reopened without losing the selection.

Why

Electron's generic edit menu reads Chromium edit flags, but the terminal renders and owns selection through its canvas-backed Ghostty surface. Those edit flags therefore disabled valid terminal actions and could not paste into the PTY. A shared in-app terminal menu keeps selection, clipboard handling, shortcut behavior, and lifecycle cancellation under the terminal's control while still routing through the local host API.

The menu is aborted when its terminal closes or is replaced, and stale requests cannot act on a removed terminal. Clipboard and chat-context eligibility are tracked separately so newline-only selections remain copyable without creating empty chat context.

UI Changes

Before

before_terminal.mp4

After

after_terminal.mp4

Validation

  • 70 focused terminal, context-menu, local API, and desktop-menu tests passed
  • Web, desktop, and contracts typechecks passed
  • Targeted lint, formatting, and git diff --check passed
  • Desktop behavior was exercised by the contributor; automated browser/computer-use verification was not run

Checklist

  • This PR is small and focused
  • I explained what changed and why
  • I included before/after screenshots for any UI changes
  • I included a video for animation/interaction changes

Generated with gpt-5.6-sol in the T3 Code Codex harness.


Note

Medium Risk
Changes terminal clipboard/menu lifecycle and extends LocalApi.contextMenu.show; optional contract fields are backward compatible, but styled menus on desktop and abort-driven focus behavior need careful regression testing.

Overview
Unifies the post-selection popup and right-click terminal menu so both show the same actions (Add to chat, Copy, Paste), platform shortcuts, and go through a shared runTerminalMenuRequest path with AbortController cancellation, superseded-request guards, and focus restore only after copy/paste.

Context menu platform changes: ContextMenuItem gains optional accelerator, wired into Electron native menus and the web fallback (shortcut labels, contextMenuAcceleratorAction, compact layout). localApi.contextMenu.show accepts presentation: "styled" (forces the DOM menu on desktop), signal, and restoreFocus; close always dismisses the fallback. The fallback also closes on outside scroll and owner abort.

Terminal behavior: Selection eligibility splits canCopy vs canAddToChat (e.g. newline-only selections stay copyable). Ghostty paste() centralizes paste and bumps pasteShortcutToken so menu paste races keyboard clipboard reads; the surface always preventDefault on context menu before the host handles it.

Reviewed by Cursor Bugbot for commit 1c7827c. Bugbot is set up for automated code reviews on this repo. Configure here.

Note

Make terminal context menu actions reliable with accelerators, abort support, and focus restoration

  • Adds keyboard accelerators to terminal context menus (copy, paste, add to chat) with platform-specific display (macOS glyphs vs Ctrl+Shift)
  • Introduces runTerminalMenuRequest in ThreadTerminalDrawer.tsx to orchestrate menu open/action/focus with abort signals and stale-request guards; only current requests perform actions or report errors
  • Extends showContextMenuFallback in contextMenuFallback.ts to support AbortSignal, accelerator key activation, outside-scroll dismissal, compact layout, and configurable focus restoration ('on-dismiss')
  • Updates GhosttyTerminalSurface.onContextMenu in surface.ts to always call event.preventDefault() itself; centralizes paste through a new paste() method
  • LocalApi.contextMenu.show now routes to the styled web fallback when presentation: 'styled' is requested, even on desktop; otherwise delegates to native menu
  • Behavioral Change: TerminalViewport no longer calls event.preventDefault() on context menu — the surface now owns this. contextMenu.close always dismisses the styled fallback regardless of desktop bridge presence.

Macroscope summarized 1c7827c.

@coderabbitai

coderabbitai Bot commented Aug 14, 2026 •

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: ea62837d-c14d-4f66-af2d-8457c8c95f59

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions github-actions Bot added the size:L 100-499 changed lines (additions + deletions). label Aug 14, 2026
Comment thread apps/web/src/terminal/ghostty/surface.ts
@github-actions github-actions Bot added the vouch:unvouched PR author is not yet trusted in the VOUCHED list. label Aug 14, 2026
Comment thread apps/web/src/components/ThreadTerminalDrawer.tsx Outdated
Comment thread apps/web/src/contextMenuFallback.ts
@macroscopeapp

macroscopeapp Bot commented Aug 14, 2026 •

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Not approved

Macroscope's review found this PR not approvable — This PR substantially changes terminal menu behavior and shared context-menu lifecycle handling across browser and desktop environments, including new shortcut dispatch, styled menus, cancellation, focus, and clipboard coordination. The cross-cutting runtime impact is broader than a small isolated bug fix and merits human review.

You can add or adjust custom eligibility rules. Learn more.

@Adamulek123
Adamulek123 force-pushed the fix/terminal-context-menu branch from 2cff9ae to 3c6c912 Compare August 14, 2026 20:24
Comment thread apps/web/src/localApi.ts
…menu

# Conflicts:
#	apps/desktop/src/electron/ElectronMenu.test.ts
#	apps/web/src/components/ThreadTerminalDrawer.tsx
#	apps/web/src/contextMenuFallback.ts
#	apps/web/src/terminal/ghostty/surface.ts
Comment thread apps/web/src/components/ThreadTerminalDrawer.tsx

@macroscopeapp macroscopeapp Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

UI Consistency — findings

The imperative fallback menu in apps/web/src/contextMenuFallback.ts has so far mirrored the React menu primitives (MenuPopup, MenuItem, MenuSeparator, MenuGroupLabel) class-for-class. This PR adds a second, hand-tuned menu design inside the same function, keyed implicitly off whether any item has an accelerator, plus a new shortcut chip treatment that doesn't match MenuShortcut/Kbd. Comments inline. One dead handler in ThreadTerminalDrawer.tsx is also flagged.

Posted via Macroscope — UI Consistency

Comment thread apps/web/src/contextMenuFallback.ts Outdated
Comment thread apps/web/src/contextMenuFallback.ts Outdated
Comment thread apps/web/src/components/ThreadTerminalDrawer.tsx
Comment thread apps/web/src/contextMenuFallback.ts
Comment thread apps/web/src/contextMenuFallback.ts
Comment thread apps/web/src/components/ThreadTerminalDrawer.tsx
Comment thread apps/web/src/components/ThreadTerminalDrawer.tsx Outdated

@macroscopeapp macroscopeapp Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

UI Consistency

The previous round's findings are addressed: the compact layout is now an explicit layout: "compact" option instead of being inferred from accelerators, the shortcut hint reuses the MenuShortcut class contract, compact rows keep a responsive type step plus opacity-64 for disabled, and handleContextMenu is wired into the surface's onContextMenu.

Three remaining items on the changed lines:

  1. apps/web/src/contextMenuFallback.ts — the accelerator's imperative style reads var(--secondary-label) instead of the appearance-contrast-adjusted var(--contrast-secondary-label), so the shortcut text splits away from the adjusted colors used everywhere else in this menu.
  2. apps/web/src/contextMenuFallback.ts — inner.dataset.compact has no consumer and emits data-compact="false" on every non-compact menu.
  3. apps/web/src/terminal/ghostty/surface.ts — preventDefault ownership moved from the host into the surface, but the onContextMenu option's doc comment still assigns that ownership to the host.

Posted via Macroscope — UI Consistency

Comment thread apps/web/src/terminal/ghostty/surface.ts
Comment thread apps/web/src/contextMenuFallback.ts
Comment thread apps/web/src/contextMenuFallback.ts

@macroscopeapp macroscopeapp Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One finding: the new shortcut <kbd> reads the unadjusted --secondary-label role in its inline style, so it bypasses the contrast bridge that every other imperative color in this file goes through.

Posted via Macroscope — UI Consistency

Comment thread apps/web/src/contextMenuFallback.ts Outdated

@macroscopeapp macroscopeapp Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One interaction finding on the terminal context menu focus contract; everything flagged in earlier runs (contrast token for the shortcut hint, data-compact, the onContextMenu doc comment, the unused handleContextMenu, MenuShortcut class parity) looks resolved.

Posted via Macroscope — UI Consistency

Comment thread apps/web/src/components/ThreadTerminalDrawer.tsx Outdated

@cursor cursor Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 475ca8e. Configure here.

Comment thread apps/web/src/components/ThreadTerminalDrawer.tsx
@Adamulek123

Copy link
Copy Markdown
Contributor Author

This PR became too broad while covering several independent terminal-menu issues. It has been split into:

Each behavior now has a focused diff and its tests beside it. #8459 will be rebased onto main and marked ready after #8458 lands.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:L 100-499 changed lines (additions + deletions). vouch:unvouched PR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant