Skip to content

Add configurable inline VS Code placement#2027

Open
austinywang wants to merge 3 commits intomainfrom
issue-1977-vscode-split-direction
Open

Add configurable inline VS Code placement#2027
austinywang wants to merge 3 commits intomainfrom
issue-1977-vscode-split-direction

Conversation

@austinywang
Copy link
Copy Markdown
Contributor

@austinywang austinywang commented Mar 24, 2026

Summary

  • add a typed vscode-inline-split-direction setting with right, left, bottom, top, and tab values
  • mirror config-file values into defaults, expose the setting in Browser Settings, and localize the new labels
  • use the configured placement when opening inline VS Code, including opening in the current pane as a tab
  • add unit coverage for settings normalization and config parsing

Closes #1977

Verification

  • ./scripts/reload.sh --tag issue-1977-vscode-split-direction
  • tests not run locally per repo policy

Summary by cubic

Make inline VS Code placement configurable: open as a split (right/left/top/bottom) or as a tab. Defaults to right; configurable in Browser Settings and via vscode-inline-split-direction (closes #1977).

  • New Features

    • Added vscode-inline-split-direction with right, left, bottom (down), top (up), tab.
    • Setting in Browser Settings with localized labels and help text.
    • Placement applied when opening inline VS Code; tab opens in the current pane.
    • Config parsed and normalized from the config file, synced to UserDefaults on load; tests added for parsing, aliases, defaults, and canonical writes.
  • Bug Fixes

    • Deferred pane lookup for tab placement to reliably find the source pane.

Written for commit 2919545. Summary will update on new commits.

Summary by CodeRabbit

  • New Features

    • Added a configurable VS Code inline split direction setting (left, right, top, bottom, tab) in Settings > Browser.
    • Added English and Japanese localizations for the new setting and related UI labels.
  • Behavior

    • Updated how inline VS Code opens to respect the chosen split/tab preference and fallback behavior when needed.
  • Tests

    • Added unit tests covering parsing, persistence, normalization, and defaults for the new setting.

@vercel
Copy link
Copy Markdown

vercel Bot commented Mar 24, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
cmux Ready Ready Preview, Comment Mar 24, 2026 8:19am

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Mar 24, 2026

📝 Walkthrough

Walkthrough

Adds a configurable setting for how inline VS Code opens (right, left, bottom, top, or tab) with config parsing, UserDefaults persistence, Settings UI, ContentView open logic changes, enum/settings types, localization (en/ja), and accompanying tests.

Changes

Cohort / File(s) Summary
Localization
Resources/Localizable.xcstrings
Added localized entries for settings.browser.vscodeInlineSplitDirection and subkeys (.bottom, .left, .right, .tab, .top, .subtitle) in English and Japanese.
Split Direction Types & Settings
Sources/Panels/BrowserPanel.swift
Added VSCodeInlineSplitDirection enum and VSCodeInlineSplitDirectionSettings for keys, parsing (aliases), default, and mapping to SplitDirection where applicable.
Config Integration
Sources/GhosttyConfig.swift
Added optional vscodeInlineSplitDirection property, parsed from config key vscode-inline-split-direction, and applyVSCodeInlineSplitDirectionToUserDefaults() to persist to UserDefaults.
Open Flow / UI Logic
Sources/ContentView.swift
Introduced @AppStorage raw setting and typed accessors; updated openFocusedDirectoryInInlineVSCode to branch: create a split when direction maps to SplitDirection, otherwise open a new browser surface in resolved pane (with early-return if pane id unresolved).
Settings UI
Sources/cmuxApp.swift
Added SettingsPickerRow to expose vscodeInlineSplitDirection in Settings, binding that normalizes/stores raw values and initializes/resets using VSCodeInlineSplitDirectionSettings.
API Change
Sources/TabManager.swift
Extended TabManager.newBrowserSurface(...) signature with optional focus: Bool? = nil and forwarded the parameter.
Tests
cmuxTests/BrowserConfigTests.swift, cmuxTests/GhosttyConfigTests.swift
Added tests for VSCodeInlineSplitDirectionSettings.current(defaults:) normalization/aliases and for config parsing + persistence behavior via GhosttyConfig.applyVSCodeInlineSplitDirectionToUserDefaults.

Sequence Diagram

sequenceDiagram
    actor User
    participant Settings as "Settings UI\n(SettingsPickerRow)"
    participant App as "AppStorage / cmuxApp"
    participant Content as "ContentView"
    participant Config as "VSCodeInlineSplitDirectionSettings"
    participant TabMgr as "TabManager"
    participant Browser as "BrowserPanel"

    User->>Settings: choose direction (right/left/bottom/top/tab)
    Settings->>App: write raw value to AppStorage
    User->>Content: trigger Open Current Directory in VS Code (Inline)
    Content->>Config: resolve current direction (AppStorage/UserDefaults/config)
    Config-->>Content: VSCodeInlineSplitDirection
    alt direction maps to a SplitDirection
        Content->>TabMgr: newBrowserSplit(orientation, insertFirst)
    else direction is tab (no SplitDirection)
        Content->>TabMgr: newBrowserSurface(inPane: resolvedPaneId)
    end
    TabMgr->>Browser: create/display browser surface (VS Code)
    Browser-->>User: VS Code panel shown in configured position
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

Possibly related PRs

Poem

🐰 A hop, a split, a tab so neat,
I choose where VS Code takes its seat,
Left or right, above or down,
Or cosy in a tably town,
I nibble settings—now complete! 🥕

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main change: adding configurability for inline VS Code placement through a new setting.
Description check ✅ Passed The description covers the what (new setting with values), why (closes #1977), and how it was verified (reload script), but lacks explicit testing and demo information.
Linked Issues check ✅ Passed The PR fully implements issue #1977: adds vscode-inline-split-direction config with right/left/bottom/top/tab values, exposes in settings, syncs to defaults, applies to inline VS Code opening, and includes unit tests.
Out of Scope Changes check ✅ Passed All changes are directly scoped to implementing the configurable inline VS Code placement feature; no unrelated modifications detected.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch issue-1977-vscode-split-direction

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 and usage tips.

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented Mar 24, 2026

Greptile Summary

This PR adds a configurable vscode-inline-split-direction setting (values: right, left, bottom, top, tab) that controls where inline VS Code opens relative to the active panel. The setting is parsed from the Ghostty config file, mirrored into UserDefaults, exposed in Browser Settings with full localization (EN + JA), and used at the call site in ContentView. The implementation follows established patterns (config parsing → UserDefaults → @AppStorage → SwiftUI picker) and is backed by solid unit tests.

Key changes:

  • New VSCodeInlineSplitDirection enum and VSCodeInlineSplitDirectionSettings helper in BrowserPanel.swift, including alias handling (down/up map to .bottom/.top).
  • GhosttyConfig parses the new key and applies it to UserDefaults at load time.
  • ContentView.openFocusedDirectoryInInlineVSCode dispatches to newBrowserSplit or newBrowserSurface based on the resolved direction.
  • TabManager.newBrowserSurface gains a focus: Bool? parameter to support the tab-open path.
  • Browser Settings picker row added with subtitle, reset wired up in onAppear and reset-all.

Issue found:

  • In ContentView.openFocusedDirectoryInInlineVSCode, sourcePaneId is resolved unconditionally in the guard even though it is only consumed in the .tab branch. If workspace.paneId(forPanelId:) returns nil for any reason, all four split directions will silently fail — a regression from the previous code that had no pane-lookup dependency for splits.

Confidence Score: 4/5

  • Safe to merge after moving the pane lookup out of the shared guard into the tab-only branch.
  • The overall structure is clean, well-tested, and consistent with existing patterns. The one concrete issue — sourcePaneId required unconditionally for all directions — is a real logic regression that can silently prevent the split-direction paths from working in edge cases, warranting one targeted fix before merge.
  • Sources/ContentView.swift — the guard condition around pane ID lookup

Important Files Changed

Filename Overview
Sources/Panels/BrowserPanel.swift Adds VSCodeInlineSplitDirection enum and VSCodeInlineSplitDirectionSettings helper. Alias handling (down.bottom, up.top) and case-insensitive parsing are well-implemented and tested.
Sources/ContentView.swift Routes inline VS Code open through new split-direction setting. sourcePaneId is resolved unconditionally in the guard but is only needed for the .tab branch, causing unnecessary early-return failures for split directions if pane lookup fails.
Sources/GhosttyConfig.swift Adds config-file parsing for vscode-inline-split-direction and mirrors it into UserDefaults on load. Pattern is consistent with other config keys in this file.
Sources/TabManager.swift Threads the new focus: Bool? parameter down to the underlying tab.newBrowserSurface call. Minimal, additive change with a safe default of nil.
Sources/cmuxApp.swift Adds the new picker row to Browser Settings, wires up @AppStorage, and keeps reset/refresh logic in sync. Follows the same pattern as adjacent settings.
cmuxTests/BrowserConfigTests.swift Good unit coverage: default fallback, invalid-value fallback, alias normalization (down/up), and each canonical value are all exercised with isolated UserDefaults suites.
cmuxTests/GhosttyConfigTests.swift Covers config-file parsing, canonical value write-back (alias down"bottom"), and no-write-on-invalid-value behaviour with isolated UserDefaults suites.
Resources/Localizable.xcstrings Adds English and Japanese localizations for all six new string keys. The new block is inserted before settings.browser.theme.subtitleForced, which is slightly out of alphabetical order (v > t), but this has no functional impact.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[openFocusedDirectoryInInlineVSCode] --> B{guard: appURL\n+ workspace\n+ sourcePanelId\n+ sourcePaneId?}
    B -- nil --> C[return false]
    B -- ok --> D[resolve vscodeInlineSplitDirection\nfrom @AppStorage]
    D --> E{ensureServeWebURL}
    E -- failure --> F[NSSound.beep]
    E -- success --> G{openDirection\n.splitDirection?}
    G -- non-nil\nright/left/top/bottom --> H[newBrowserSplit\nfromPanelId: sourcePanelId\norientation + insertFirst]
    G -- nil\ntab --> I[newBrowserSurface\ninPane: sourcePaneId\nfocus: true]
    H --> J{createdPanelId != nil?}
    I --> J
    J -- nil --> F
    J -- ok --> K[return true]

    subgraph Settings Load
        L[GhosttyConfig.loadFromDisk] --> M[parse config file\nvscode-inline-split-direction]
        M --> N[applyVSCodeInlineSplitDirectionToUserDefaults]
        N --> O[UserDefaults\nvscodeInlineSplitDirection]
    end

    subgraph Settings UI
        P[SettingsView @AppStorage] --> Q[SettingsPickerRow\nright/left/bottom/top/tab]
        Q --> O
    end

    O --> D
Loading

Reviews (1): Last reviewed commit: "fix: make inline vscode placement config..." | Re-trigger Greptile

Comment thread Sources/ContentView.swift
Comment on lines 7362 to 7368
private func openFocusedDirectoryInInlineVSCode(_ directoryURL: URL) -> Bool {
guard let vscodeApplicationURL = TerminalDirectoryOpenTarget.vscodeInline.applicationURL(),
let workspace = tabManager.selectedWorkspace,
let sourcePanelId = workspace.focusedPanelId else {
let sourcePanelId = workspace.focusedPanelId,
let sourcePaneId = workspace.paneId(forPanelId: sourcePanelId) else {
return false
}
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.

P1 sourcePaneId required unconditionally but only used in the tab branch

sourcePaneId is resolved in the guard clause and will cause an early false return if paneId(forPanelId:) comes back nil — but it is only consumed in the .tab branch below. For any of the four split directions (right, left, bottom, top), the function will silently fail via NSSound.beep() if paneId(forPanelId:) ever returns nil (e.g. because surfaceIdFromPanelId has no entry for the panel), even though those code paths never touch sourcePaneId.

This is a behavioural regression from the previous code, which only required sourcePanelId and had no dependency on pane lookup.

Consider resolving sourcePaneId lazily, only when the tab branch is actually taken:

guard let vscodeApplicationURL = TerminalDirectoryOpenTarget.vscodeInline.applicationURL(),
      let workspace = tabManager.selectedWorkspace,
      let sourcePanelId = workspace.focusedPanelId else {
    return false
}
let sourceTabId = workspace.id
let openDirection = vscodeInlineSplitDirection
let tabManager = tabManager
VSCodeServeWebController.shared.ensureServeWebURL(vscodeApplicationURL: vscodeApplicationURL) { serveWebURL in
    // ...
    let createdPanelId: UUID? = {
        if let splitDirection = openDirection.splitDirection {
            return tabManager.newBrowserSplit(
                tabId: sourceTabId,
                fromPanelId: sourcePanelId,
                orientation: splitDirection.orientation,
                insertFirst: splitDirection.insertFirst,
                url: openFolderURL,
                focus: true
            )
        }
        guard let sourcePaneId = workspace.paneId(forPanelId: sourcePanelId) else {
            NSSound.beep()
            return nil
        }
        return tabManager.newBrowserSurface(
            tabId: sourceTabId,
            inPane: sourcePaneId,
            url: openFolderURL,
            focus: true
        )
    }()
    // ...
}

Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

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

No issues found across 8 files

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
Sources/ContentView.swift (1)

7363-7399: ⚠️ Potential issue | 🟠 Major

Avoid making every placement depend on paneId(forPanelId:).

Line 7366 now short-circuits the whole action when the focused panel is temporarily not pane-backed. That makes left/right/top/bottom fail even though those branches only need sourcePanelId, and it skips the split-then-surface fallback pattern this file already relies on for file-open flows.

♻️ Suggested fallback pattern
 private func openFocusedDirectoryInInlineVSCode(_ directoryURL: URL) -> Bool {
     guard let vscodeApplicationURL = TerminalDirectoryOpenTarget.vscodeInline.applicationURL(),
           let workspace = tabManager.selectedWorkspace,
-          let sourcePanelId = workspace.focusedPanelId,
-          let sourcePaneId = workspace.paneId(forPanelId: sourcePanelId) else {
+          let sourcePanelId = workspace.focusedPanelId else {
         return false
     }
     let sourceTabId = workspace.id
     let openDirection = vscodeInlineSplitDirection
     let tabManager = tabManager
@@
             let createdPanelId: UUID? = {
-                if let splitDirection = openDirection.splitDirection {
-                    return tabManager.newBrowserSplit(
+                if let splitDirection = openDirection.splitDirection,
+                   let panelId = tabManager.newBrowserSplit(
                         tabId: sourceTabId,
                         fromPanelId: sourcePanelId,
                         orientation: splitDirection.orientation,
                         insertFirst: splitDirection.insertFirst,
                         url: openFolderURL,
                         focus: true
-                    )
+                    ) {
+                    return panelId
                 }
+                guard let focusedPaneId = workspace.bonsplitController.focusedPaneId else { return nil }
                 return tabManager.newBrowserSurface(
                     tabId: sourceTabId,
-                    inPane: sourcePaneId,
+                    inPane: focusedPaneId,
                     url: openFolderURL,
                     focus: true
                 )
             }()

Based on learnings: openFileInTextEditor(_:) must fall back to workspace.newTextEditorSurface(inPane: bonsplitController.focusedPaneId) so file-open requests aren’t dropped when the focused panel is not pane-backed.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Sources/ContentView.swift` around lines 7363 - 7399, The guard currently
requires paneId(forPanelId:) up front which makes the whole action fail when the
focused panel isn't pane-backed; change openFileInTextEditor(_:) (and the VSCode
open-folder flow) to only require workspace.focusedPanelId initially, defer
resolving paneId by calling workspace.paneId(forPanelId: sourcePanelId) only
where a pane-backed surface is actually needed (e.g., before calling
newBrowserSurface or workspace.newTextEditorSurface), and implement the fallback
path: if paneId is nil use bonsplitController.focusedPaneId or call
workspace.newTextEditorSurface(inPane: bonsplitController.focusedPaneId) so
file-open and split branches still work when the focused panel is not
pane-backed; keep newBrowserSplit logic unchanged (it only needs sourcePanelId)
and only branch to newBrowserSurface when you have a paneId or the fallback
pane.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@Sources/ContentView.swift`:
- Around line 7363-7399: The guard currently requires paneId(forPanelId:) up
front which makes the whole action fail when the focused panel isn't
pane-backed; change openFileInTextEditor(_:) (and the VSCode open-folder flow)
to only require workspace.focusedPanelId initially, defer resolving paneId by
calling workspace.paneId(forPanelId: sourcePanelId) only where a pane-backed
surface is actually needed (e.g., before calling newBrowserSurface or
workspace.newTextEditorSurface), and implement the fallback path: if paneId is
nil use bonsplitController.focusedPaneId or call
workspace.newTextEditorSurface(inPane: bonsplitController.focusedPaneId) so
file-open and split branches still work when the focused panel is not
pane-backed; keep newBrowserSplit logic unchanged (it only needs sourcePanelId)
and only branch to newBrowserSurface when you have a paneId or the fallback
pane.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 47b380d2-fa29-474c-aff9-f53eb5b1f0c9

📥 Commits

Reviewing files that changed from the base of the PR and between 142c62c and d74a5ed.

📒 Files selected for processing (8)
  • Resources/Localizable.xcstrings
  • Sources/ContentView.swift
  • Sources/GhosttyConfig.swift
  • Sources/Panels/BrowserPanel.swift
  • Sources/TabManager.swift
  • Sources/cmuxApp.swift
  • cmuxTests/BrowserConfigTests.swift
  • cmuxTests/GhosttyConfigTests.swift

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@Sources/ContentView.swift`:
- Around line 7381-7403: When creating a new browser panel, if
tabManager.newBrowserSplit(...) returns nil (e.g., focused panel isn't
pane-backed) fall back to creating a surface in the focused pane instead of
bailing out; update the closure that computes createdPanelId so when
openDirection.splitDirection exists but newBrowserSplit returns nil you call
tabManager.newBrowserSurface(inPane: focusedPaneId, url: ..., focus: true) using
bonsplitController.focusedPaneId (or fallbackPaneId if needed), and similarly
when resolving sourcePaneId fallback to the focused pane before returning nil,
so newBrowserSurface is attempted whenever a split cannot be created.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 4a4ed6d1-97b4-4862-ab5d-b7bb56a5ae9d

📥 Commits

Reviewing files that changed from the base of the PR and between d74a5ed and 2919545.

📒 Files selected for processing (1)
  • Sources/ContentView.swift

Comment thread Sources/ContentView.swift
Comment on lines +7381 to 7403
let createdPanelId: UUID? = {
if let splitDirection = openDirection.splitDirection {
return tabManager.newBrowserSplit(
tabId: sourceTabId,
fromPanelId: sourcePanelId,
orientation: splitDirection.orientation,
insertFirst: splitDirection.insertFirst,
url: openFolderURL,
focus: true
)
}
guard let sourcePaneId = workspace.paneId(forPanelId: sourcePanelId) ?? fallbackPaneId else {
return nil
}
return tabManager.newBrowserSurface(
tabId: sourceTabId,
inPane: sourcePaneId,
url: openFolderURL,
focus: true
)
}()
guard createdPanelId != nil else {
NSSound.beep()
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Fall back to opening in the focused pane when split creation fails.

If newBrowserSplit(...) returns nil because the focused panel is not pane-backed, this still drops the inline VS Code open even though fallbackPaneId is already available. Falling back to newBrowserSurface(inPane:) here would keep left/right/top/bottom placements from failing unnecessarily.

Suggested fallback
             let createdPanelId: UUID? = {
-                if let splitDirection = openDirection.splitDirection {
-                    return tabManager.newBrowserSplit(
+                if let splitDirection = openDirection.splitDirection,
+                   let splitPanelId = tabManager.newBrowserSplit(
                         tabId: sourceTabId,
                         fromPanelId: sourcePanelId,
                         orientation: splitDirection.orientation,
                         insertFirst: splitDirection.insertFirst,
                         url: openFolderURL,
                         focus: true
-                    )
+                    ) {
+                    return splitPanelId
                 }
                 guard let sourcePaneId = workspace.paneId(forPanelId: sourcePanelId) ?? fallbackPaneId else {
                     return nil
                 }
                 return tabManager.newBrowserSurface(

Based on learnings, In Sources/ContentView.swift, openFileInTextEditor(_:) must attempt workspace.newTextEditorSplit(from:orientation:filePath:focus:) and, if that returns nil, fall back to workspace.newTextEditorSurface(inPane:filePath:focus:) using bonsplitController.focusedPaneId.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
let createdPanelId: UUID? = {
if let splitDirection = openDirection.splitDirection {
return tabManager.newBrowserSplit(
tabId: sourceTabId,
fromPanelId: sourcePanelId,
orientation: splitDirection.orientation,
insertFirst: splitDirection.insertFirst,
url: openFolderURL,
focus: true
)
}
guard let sourcePaneId = workspace.paneId(forPanelId: sourcePanelId) ?? fallbackPaneId else {
return nil
}
return tabManager.newBrowserSurface(
tabId: sourceTabId,
inPane: sourcePaneId,
url: openFolderURL,
focus: true
)
}()
guard createdPanelId != nil else {
NSSound.beep()
let createdPanelId: UUID? = {
if let splitDirection = openDirection.splitDirection,
let splitPanelId = tabManager.newBrowserSplit(
tabId: sourceTabId,
fromPanelId: sourcePanelId,
orientation: splitDirection.orientation,
insertFirst: splitDirection.insertFirst,
url: openFolderURL,
focus: true
) {
return splitPanelId
}
guard let sourcePaneId = workspace.paneId(forPanelId: sourcePanelId) ?? fallbackPaneId else {
return nil
}
return tabManager.newBrowserSurface(
tabId: sourceTabId,
inPane: sourcePaneId,
url: openFolderURL,
focus: true
)
}()
guard createdPanelId != nil else {
NSSound.beep()
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Sources/ContentView.swift` around lines 7381 - 7403, When creating a new
browser panel, if tabManager.newBrowserSplit(...) returns nil (e.g., focused
panel isn't pane-backed) fall back to creating a surface in the focused pane
instead of bailing out; update the closure that computes createdPanelId so when
openDirection.splitDirection exists but newBrowserSplit returns nil you call
tabManager.newBrowserSurface(inPane: focusedPaneId, url: ..., focus: true) using
bonsplitController.focusedPaneId (or fallbackPaneId if needed), and similarly
when resolving sourcePaneId fallback to the focused pane before returning nil,
so newBrowserSurface is attempted whenever a split cannot be created.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Configurable split direction for inline VS Code panel

1 participant