feat(desktop): add an "Open in" submenu to terminal link right-clicks

Merged
SA
2mo ago
+641-72

Summary

  • Right-clicking a link in a terminal now offers Open in ▸ at the top of the context menu, with the same three destinations that link kind already has in Settings → Links.
  • The entry is hidden entirely when the right-click did not land on a link, so the menu is unchanged everywhere else.

Screenshots

Right-clicking a linkified URL, file path, and folder in a terminal. Hosted on the
pr-7179-screenshots branch (same pattern as pr-6787-screenshots) and pinned by commit SHA,
so they never enter main's tree.

URLFile pathFolder

Why / Context

Terminal links were reachable only by modifier-click, and the bindings are invisible unless you go and read Settings → Links (or hover long enough for the hint). Defaults are plain: null, ⇧ → new browser tab, ⌘ → in-app browser pane, ⌘⇧ → default browser — so a plain click on a URL does nothing at all, which is a confusing first experience. The right-click menu is the discoverable place for "where should this open?", and it had no link items at all.

How It Works

Each link kind gets its own trio, named the way Settings → Links already names them:

right-clickedsubmenu
URLIn-App Browser · New Browser Tab · Default Browser
file pathTab · New Tab · Editor
folderSidebar · Editor · Finder

The pane context menu is built in usePaneRegistry, which can see neither the hovered link nor the hooks that open files, folders and URLs. TerminalPane therefore publishes both into a small store on contextmenu — capture phase, before Radix opens the menu, while the pointer is still over the link. Recording on the event rather than reading live hover state is what keeps the two in step: a right-click on blank terminal records null, so a stale link from an earlier hover can never leak into the menu.

Three supporting changes:

  • packages/panes: ContextMenuActionConfig gains hidden?: boolean | ((ctx) => boolean), evaluated when the menu opens rather than when the action array is memoized. Without it an entry cannot depend on state that changes between opens — resolvedContextMenuActions is a useMemo on [context, contextMenuActions, definition], and subscribing the whole registry to hover state would rebuild every pane definition on every mouse move.
  • LinkHoverInfo now carries the URL (it previously only said kind: "url") and the file's row/col, threaded through all three link providers (LinkDetectorAdapter, UrlLinkProvider + its OSC 8 handler, WordLinkDetector).
  • runTerminalLinkAction is now shared by the modifier-click handlers and the menu, so the two paths cannot drift apart.

Manual QA

Driven over CDP against the dev app (v2 workspace, real terminal, real host service):

  • Right-click a URL → Open in ▸ shows In-App Browser / New Browser Tab / Default Browser
  • Right-click an absolute file path → Tab / New Tab / Editor
  • Right-click a directory path → Sidebar / Editor / Finder
  • Right-click on non-link terminal output → no Open in, no stray separator; menu byte-for-byte as before
  • Right-click a word that looks like a path but does not resolve (AGENTS.md in an empty cwd) → no Open in, since no link is detected
  • Open in → In-App Browser on https://example.com/abc opens a browser pane at exactly that URL
  • Open in → New Browser Tab opens a new tab with a browser pane
  • Windows/Linux (macOS only here — nothing platform-specific in the change, but the Finder entry is macOS-shaped and matches the existing folder policy)

Testing

  • bun run typecheck — @superset/desktop and @superset/panes clean
  • bun run lint — clean
  • bun run check:i18n — clean; 5 new ids (In-App Browser, New Browser Tab, Default Browser, Editor, Finder) translated across all 16 locales. "Open in", "Tab", "New Tab" and "Sidebar" reuse existing entries — each verified to be the same referent at its existing call sites, so no context split was needed.
  • bunx sherif — no issues
  • bun run --filter=@superset/panes test — 110 pass
  • bun run --filter=@superset/desktop test — 3469 pass, 1 pre-existing env failure (LeaderboardRank asserts https://superset.sh/... while this worktree's .env sets NEXT_PUBLIC_MARKETING_URL=http://localhost:8202; untouched by this diff)
  • bun turbo run build --filter=@superset/desktop
  • Updated one assertion in terminal-link-manager.test.ts that pinned the old { kind: "url" } hover shape.

Design Decisions

  • hidden on the action config instead of rebuilding the registry. Making the menu link-aware by subscribing usePaneRegistry to hover state would re-create every pane definition on every mouse move over a link. A predicate evaluated at open time costs nothing and keeps the hot path untouched.
  • Snapshot on contextmenu, not live hover state. Radix opens the menu under the cursor, which can make xterm fire leave between the click and the menu render. Capturing in the capture-phase handler removes that race.
  • Terminal-specific modules stay under TerminalPane/ even though usePaneRegistry imports them. That follows the existing arrangement in this folder — usePaneRegistry.tsx already reaches into TerminalPane/components/ for TerminalPaneHeaderExtras, TerminalPaneIcon and TerminalSessionDropdown.
  • No "Copy Link Address". The existing Copy already covers the selection, and pairing a copy action with an "Open in" group read oddly.

Known Limitations

  • UrlLinkProvider's hard-wrap joining over-captures when a URL sits at the very end of a line immediately above the prompt: https://superset.sh/docs becomes https://superset.sh/docsrelay-v1-decommission-2. Pre-existing and not introduced here — xterm hands activate and hover the same link.text and both forward it unchanged, so the menu opens exactly what a modifier-click would open. Worth its own fix.
  • Only the v2 terminal pane. v1 (screens/main) is being deleted, so it was deliberately left alone.

https://claude.ai/code/session_01DNoj8JhjGwTRs9AoxYYRB9

Summary by CodeRabbit

  • New Features

    • Added an “Open in” submenu for terminal links, including browsers, editors, Finder, workspace tabs, and in-app navigation.
    • File links preserve row and column positions when opened.
    • Folder links can be opened, revealed, or shown in the sidebar where applicable.
  • Bug Fixes

    • Improved URL and file-link hover information and right-click handling.
    • Context menus now accurately reflect the link under the pointer.
  • Localization

    • Added translations for browser, editor, Finder, and tab labels across supported languages.