Skip to content

Per-pane full-width tab mode with prominent title header - #159

Merged
azooz2003-bit merged 7 commits into
mainfrom
feat-pane-full-width-tab-header
Jul 7, 2026
Merged

azooz2003-bit merged 7 commits into
mainfrom
feat-pane-full-width-tab-header

Conversation

@azooz2003-bit

@azooz2003-bit azooz2003-bit commented Jul 6, 2026 •

Copy link
Copy Markdown

Adds a per-pane fullWidthTabMode: when enabled, the pane header renders a prominent full-width title of the selected tab instead of the tab strip. Same height as the tab bar, live title updates, subtle index/count badge when more tabs exist, right-click anywhere on the header opens the selected tab's context menu (the exit path), no new-tab button. Adds TabContextAction.toggleFullWidthTab, per-pane controller API (setFullWidthTabMode/isFullWidthTabMode/toggleFullWidthTabMode/fullWidthTabModePaneIds), en+ja strings, and tests (163 passing).

Consumed by the cmux PR that wires this to the command palette and tab context menu (link added there once open).

🤖 Generated with Claude Code


View with Codesmith Autofix with Codesmith
Need help on this PR? Tag /codesmith with what you need. Autofix is disabled.


Summary by cubic

Adds a per-pane full-width tab mode that replaces the tab strip with a prominent, full-width title header for the selected tab. The header matches tab chrome, supports drag & drop, keeps key tab/pane actions, and toggling from context now selects the target tab first; it’s opt-in per pane.

  • New Features

    • Header shows the selected tab’s title and icon with live updates, adds an index/total badge, aligns with tab bar chrome (height, active indicator, separator), and respects tab bar visibility; no new‑tab button.
    • Preserves actions: right‑click opens the selected tab’s context menu with a toggleFullWidthTab item (label switches between “Full Width Tab” and “Exit Full Width Tab”); adds a tab switcher menu via the badge and a pane actions menu for configured split buttons (BonsplitConfiguration.splitButtons).
    • Dragging from the header starts a tab drag with preview; dropping .tabTransfer/.fileURL appends at the end with a focus‑aware hover highlight. A shared SplitViewController+TabDrag helper is used by the header, tab strip, and manual reorder.
    • BonsplitController handles TabContextAction.toggleFullWidthTab; adds onTabFullWidthToggleRequest for hosts, plus per‑pane APIs: setFullWidthTabMode(_:inPane:), isFullWidthTabMode(inPane:), toggleFullWidthTabMode(inPane:), fullWidthTabModePaneIds; en/ja strings and tests.
  • Bug Fixes

    • Toggling full‑width from a tab’s context menu selects that tab first to keep state consistent.
    • Cancelled tab drags clear state and restore one‑shot event monitor cleanup to prevent leaks.

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

Review in cubic

Summary by CodeRabbit

  • New Features
    • Added Full Width Tab Mode with a dedicated full-width selected-tab header layout when enabled for a pane.
    • Added a context-menu action to enter/exit full-width tab mode; tab title/icon presentation updates accordingly.
    • Exposed controller APIs to query, set, and toggle full-width mode per pane, plus a list of pane IDs currently in that mode.
  • Bug Fixes
    • Full-width mode state is now reliably cleared when a pane is closed, including after split replacements.
  • Localization
    • Added translations for “Full Width Tab” and “Exit Full Width Tab” in supported languages.

When enabled for a pane, the header renders a prominent full-width title
of the selected tab instead of the tab strip: same height, live title
updates, subtle index/count badge when extra tabs exist, right-click
opens the selected tab's context menu (including the exit item), no
new-tab button. New TabContextAction.toggleFullWidthTab and per-pane
BonsplitController API (set/get/toggle/list), en+ja strings, tests.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jul 6, 2026 •

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

This PR adds per-pane full-width tab mode, a dedicated header view, context menu support, drag handling helpers, controller APIs, localization, and tests.

Changes

Full Width Tab Mode

Layer / File(s) Summary
Pane state and controller API
Sources/Bonsplit/Internal/Models/PaneState.swift, Sources/Bonsplit/Public/BonsplitController.swift, Tests/BonsplitTests/BonsplitTests.swift
Adds the pane-level full-width tab flag, exposes controller methods to query and mutate it, and covers those APIs with controller tests.
Full-width header rendering
Sources/Bonsplit/Internal/Views/FullWidthTabHeaderView.swift, Sources/Bonsplit/Internal/Views/PaneContainerView.swift, Tests/BonsplitTests/BonsplitTests.swift
Adds the full-width header view, renders it from the pane container when enabled, and covers the header chrome and indicator rendering with tests and helpers.
Context menu toggle
Sources/Bonsplit/Public/Types/TabContextAction.swift, Sources/Bonsplit/Internal/Views/TabBarView.swift, Sources/Bonsplit/Internal/Views/TabItemView.swift, Sources/Bonsplit/Resources/en.lproj/Localizable.strings, Sources/Bonsplit/Resources/ja.lproj/Localizable.strings, Tests/BonsplitTests/BonsplitTests.swift
Adds the full-width tab context action, threads mode state into menu building, widens the presenter visibility, adds localized labels, and covers the menu entries with tests.
Tab drag handling refactor
Sources/Bonsplit/Internal/Controllers/SplitViewController+TabDrag.swift, Sources/Bonsplit/Internal/Views/TabBarView.swift, Tests/BonsplitTests/BonsplitTests.swift
Moves tab-drag setup and cleanup into SplitViewController helpers, updates tab bar drag start and provider creation to use them, and adds drag-generation tests.

Estimated code review effort: 4 (Complex) | ~60 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: per-pane full-width tab mode with a prominent title header.
✨ 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 feat-pane-full-width-tab-header

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.

@azooz2003-bit

Copy link
Copy Markdown
Author

Consumer PR: manaflow-ai/cmux#7425

@greptile-apps

greptile-apps Bot commented Jul 6, 2026 •

Copy link
Copy Markdown

Greptile Summary

This PR introduces a per-pane fullWidthTabMode that replaces the tab strip with a prominent full-width title header showing the selected tab's icon, title, and an index/count badge when multiple tabs exist. It adds a new FullWidthTabHeaderView, public controller API (setFullWidthTabMode/isFullWidthTabMode/toggleFullWidthTabMode/fullWidthTabModePaneIds), a TabContextAction.toggleFullWidthTab enum case, en+ja strings, and 5 new tests.

  • New FullWidthTabHeaderView renders the selected tab as a full-width header with right-click context menu support (the documented exit path) and tap-to-focus; TabContextMenuPresenter is widened from private to internal to enable this.
  • TabContextMenuState gains isFullWidthTabMode and a new convenience @MainActor init that consolidates the construction logic previously duplicated in TabBarView.
  • Public API on BonsplitController manages the mode per-pane; the TabContextAction.toggleFullWidthTab case is the advertised exit path but currently relies entirely on host-delegate wiring with no internal fallback.

Confidence Score: 3/5

The core view and API are sound, but the advertised right-click exit path is a silent no-op without explicit host-delegate wiring, and full-width mode ignores the tabBarVisibility = .never configuration.

Two real defects exist in the changed code. First, requestTabContextAction(.toggleFullWidthTab) has no internal fallback: the PR documented exit path silently does nothing until the consuming host delegate calls toggleFullWidthTabMode(inPane:) — a step not yet done. Second, PaneContainerView checks isFullWidthTabMode before the tabBarVisibility guard, so a pane configured with tabBarVisibility = .never will unexpectedly show the full-width header once the mode is enabled.

BonsplitController.swift (missing internal handler for .toggleFullWidthTab) and PaneContainerView.swift (full-width check bypasses tabBarVisibility).

Important Files Changed

Filename Overview
Sources/Bonsplit/Internal/Models/PaneState.swift Adds isFullWidthTabMode: Bool = false property and matching init parameter; straightforward and safe.
Sources/Bonsplit/Internal/Views/FullWidthTabHeaderView.swift New view: renders the selected tab as a full-width title header with context menu and tap-to-focus. Has a redundant contentShape modifier. The context menu exit path is only functional if the host's delegate handles .toggleFullWidthTab.
Sources/Bonsplit/Internal/Views/PaneContainerView.swift Routes to FullWidthTabHeaderView before the tabBarVisibility check, so full-width mode bypasses host-configured tabBarVisibility = .never.
Sources/Bonsplit/Internal/Views/TabBarView.swift Adds isFullWidthTabMode to TabContextMenuState and extracts context-state construction into a new @MainActor init; refactoring is clean and logic is preserved.
Sources/Bonsplit/Internal/Views/TabItemView.swift Adds 'Full Width Tab' / 'Exit Full Width Tab' toggle to the context menu builder and widens TabContextMenuPresenter visibility from private to internal so FullWidthTabHeaderView can use it.
Sources/Bonsplit/Public/BonsplitController.swift Adds public full-width tab mode API (set/is/toggle/list). Does not add an internal fallback in requestTabContextAction for .toggleFullWidthTab, leaving the context menu exit path dependent on host-delegate wiring.
Sources/Bonsplit/Public/Types/TabContextAction.swift Adds toggleFullWidthTab case to the public enum; one-line change with no issues.
Sources/Bonsplit/Resources/en.lproj/Localizable.strings Adds English localisation keys for enter/exit full-width tab; correctly placed adjacent to the zoom strings.
Sources/Bonsplit/Resources/ja.lproj/Localizable.strings Adds Japanese localisation keys for enter/exit full-width tab; translations look correct.
Tests/BonsplitTests/BonsplitTests.swift Adds 5 new tests covering API state, per-pane independence, closed-pane cleanup, and context menu title toggling. No integration test verifies that requestTabContextAction(.toggleFullWidthTab) actually exits the mode.

Sequence Diagram

%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
    participant User
    participant FullWidthTabHeaderView
    participant TabContextMenuPresenter
    participant BonsplitController
    participant Delegate as Host Delegate

    User->>FullWidthTabHeaderView: right-click
    FullWidthTabHeaderView->>TabContextMenuPresenter: show context menu
    TabContextMenuPresenter-->>User: menu with "Exit Full Width Tab"
    User->>TabContextMenuPresenter: select "Exit Full Width Tab"
    TabContextMenuPresenter->>FullWidthTabHeaderView: onContextAction(.toggleFullWidthTab)
    FullWidthTabHeaderView->>BonsplitController: requestTabContextAction(.toggleFullWidthTab, ...)
    BonsplitController->>Delegate: didRequestTabContextAction(.toggleFullWidthTab, ...)
    Note over Delegate: Host must call toggleFullWidthTabMode(inPane:) — no internal fallback
    Delegate-->>BonsplitController: toggleFullWidthTabMode(inPane:)
    BonsplitController-->>FullWidthTabHeaderView: "pane.isFullWidthTabMode = false"
    FullWidthTabHeaderView-->>User: reverts to TabBarView
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
sequenceDiagram
    participant User
    participant FullWidthTabHeaderView
    participant TabContextMenuPresenter
    participant BonsplitController
    participant Delegate as Host Delegate

    User->>FullWidthTabHeaderView: right-click
    FullWidthTabHeaderView->>TabContextMenuPresenter: show context menu
    TabContextMenuPresenter-->>User: menu with "Exit Full Width Tab"
    User->>TabContextMenuPresenter: select "Exit Full Width Tab"
    TabContextMenuPresenter->>FullWidthTabHeaderView: onContextAction(.toggleFullWidthTab)
    FullWidthTabHeaderView->>BonsplitController: requestTabContextAction(.toggleFullWidthTab, ...)
    BonsplitController->>Delegate: didRequestTabContextAction(.toggleFullWidthTab, ...)
    Note over Delegate: Host must call toggleFullWidthTabMode(inPane:) — no internal fallback
    Delegate-->>BonsplitController: toggleFullWidthTabMode(inPane:)
    BonsplitController-->>FullWidthTabHeaderView: "pane.isFullWidthTabMode = false"
    FullWidthTabHeaderView-->>User: reverts to TabBarView
Loading

Comments Outside Diff (1)

  1. Sources/Bonsplit/Public/BonsplitController.swift, line 215-218 (link)

    P1 Exit path for full-width mode never fires without delegate wiring

    requestTabContextAction forwards every action — including .toggleFullWidthTab — exclusively through the delegate. The PR describes "right-click anywhere on the header opens the selected tab's context menu (the exit path)", but that path silently does nothing until a host app's delegate explicitly calls toggleFullWidthTabMode(inPane:) for .toggleFullWidthTab. Because isFullWidthTabMode is purely Bonsplit-internal state (unlike zoom which has host-specific behavior), there is no reason to require the host to relay the action back. Adding an internal fallback inside requestTabContextAction — mirroring how togglePaneZoom handles .toggleZoom — would make the feature self-contained and prevent a silent no-op when the consuming host hasn't yet wired the new action case.

Reviews (1): Last reviewed commit: "Add per-pane full-width tab mode with pr..." | Re-trigger Greptile

Comment on lines +173 to +178
if pane.isFullWidthTabMode, !pane.tabs.isEmpty {
FullWidthTabHeaderView(
pane: pane,
isFocused: isFocused
)
} else if tabBarVisibility.showsTabBar(tabCount: pane.tabs.count) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 FullWidthTabHeaderView bypasses tabBarVisibility configuration

The full-width header check is placed before the tabBarVisibility.showsTabBar(...) guard, so it fires regardless of the configured visibility policy. If a host app sets tabBarVisibility = .never (or uses an .auto/threshold variant that would hide the bar for the current tab count), calling setFullWidthTabMode(true, inPane:) will still render a header — overriding the app's explicit "no tab chrome" decision. The guard should respect the same visibility policy: isFullWidthTabMode should only take effect when tabBarVisibility would otherwise allow chrome to be shown, or at a minimum should be gated on tabBarVisibility != .never.

Comment on lines +78 to +83
.contentShape(Rectangle())
.onTapGesture {
withTransaction(Transaction(animation: nil)) {
controller.focusPane(pane.id)
}
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Redundant contentShape(Rectangle()) applied twice

.contentShape(Rectangle()) appears both on the inner content view at line 43 and again on the outer Group at line 78. The outer modifier supersedes the inner one, making the inner one a no-op. Consider removing the one at line 43 to keep the modifier hierarchy clear.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (2)
Sources/Bonsplit/Internal/Views/FullWidthTabHeaderView.swift (2)

105-125: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Index/count badge is invisible to VoiceOver.

.accessibilityElement(children: .ignore) collapses the whole header to just tab.title, so the visually-shown "index/count" pill (Lines 105-120) is never announced to assistive tech.

♿️ Proposed fix
-                .accessibilityElement(children: .ignore)
-                .accessibilityLabel(tab.title)
+                .accessibilityElement(children: .ignore)
+                .accessibilityLabel(
+                    pane.tabs.count > 1
+                        ? "\(tab.title), tab \(index + 1) of \(pane.tabs.count)"
+                        : tab.title
+                )
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@Sources/Bonsplit/Internal/Views/FullWidthTabHeaderView.swift` around lines
105 - 125, The index/count badge in FullWidthTabHeaderView is hidden from
VoiceOver because the header is collapsed to only tab.title by
accessibilityElement(children: .ignore). Update the accessibility setup for the
header HStack so the badge text is exposed as part of the accessible content,
either by combining the title and "\(index + 1)/\(pane.tabs.count)" into the
accessibility label or by making the badge its own accessible element while
keeping the tab header readable.

92-92: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

Font sizes derived from appearance.tabTitleFontSize aren't fully guarded against non-finite values.

Line 92 uses appearance.tabTitleFontSize + 2 directly with no clamp at all, and Lines 109/129 use max(...), which only protects against NaN (the non-NaN operand wins) but not against +infinity propagating through to .font(size:)/NSFont creation if a host misconfigures tabTitleFontSize.

Based on learnings, a prior review of TabBarTypography.swift in this repo flagged this exact max() behavior as insufficient protection against non-finite font sizes reaching NSFont.

Also applies to: 109-109, 127-146

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@Sources/Bonsplit/Internal/Views/FullWidthTabHeaderView.swift` at line 92,
Guard all font-size calculations in FullWidthTabHeaderView against non-finite
values, not just NaN. Update the uses of appearance.tabTitleFontSize in the
font-building paths (including the .font call in the title view and the other
size computations later in the view) so they sanitize or clamp to a finite
default before passing into .font(size:) or NSFont creation. Use the existing
font-size code paths in FullWidthTabHeaderView as the fix location and ensure
any arithmetic like tabTitleFontSize + 2 cannot propagate infinity.

Source: Learnings

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@Sources/Bonsplit/Internal/Views/FullWidthTabHeaderView.swift`:
- Around line 127-146: The custom image path in tabIcon(for:) applies no
saturation adjustment, so icons loaded from tab.iconImageData stay fully colored
when the view is unfocused. Update the NSImage-based branch to apply the same
saturation behavior used for the SF Symbol branch, using the existing saturation
value and iconTint/appearance state so both image types dim consistently.

---

Nitpick comments:
In `@Sources/Bonsplit/Internal/Views/FullWidthTabHeaderView.swift`:
- Around line 105-125: The index/count badge in FullWidthTabHeaderView is hidden
from VoiceOver because the header is collapsed to only tab.title by
accessibilityElement(children: .ignore). Update the accessibility setup for the
header HStack so the badge text is exposed as part of the accessible content,
either by combining the title and "\(index + 1)/\(pane.tabs.count)" into the
accessibility label or by making the badge its own accessible element while
keeping the tab header readable.
- Line 92: Guard all font-size calculations in FullWidthTabHeaderView against
non-finite values, not just NaN. Update the uses of appearance.tabTitleFontSize
in the font-building paths (including the .font call in the title view and the
other size computations later in the view) so they sanitize or clamp to a finite
default before passing into .font(size:) or NSFont creation. Use the existing
font-size code paths in FullWidthTabHeaderView as the fix location and ensure
any arithmetic like tabTitleFontSize + 2 cannot propagate infinity.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 9bca9f42-e355-4f6f-acf9-d7986ed6dac6

📥 Commits

Reviewing files that changed from the base of the PR and between 01751ef and 65c77f8.

📒 Files selected for processing (10)
  • Sources/Bonsplit/Internal/Models/PaneState.swift
  • Sources/Bonsplit/Internal/Views/FullWidthTabHeaderView.swift
  • Sources/Bonsplit/Internal/Views/PaneContainerView.swift
  • Sources/Bonsplit/Internal/Views/TabBarView.swift
  • Sources/Bonsplit/Internal/Views/TabItemView.swift
  • Sources/Bonsplit/Public/BonsplitController.swift
  • Sources/Bonsplit/Public/Types/TabContextAction.swift
  • Sources/Bonsplit/Resources/en.lproj/Localizable.strings
  • Sources/Bonsplit/Resources/ja.lproj/Localizable.strings
  • Tests/BonsplitTests/BonsplitTests.swift

Comment thread Sources/Bonsplit/Internal/Views/FullWidthTabHeaderView.swift
Dragging the header starts a drag of the selected tab via a shared
SplitViewController+TabDrag helper (same provider, preview, drag-state
bookkeeping, and cancelled-drag cleanup as the tab strip; strip and
manual reorder now route through it too). The header accepts
.tabTransfer/.fileURL drops appended at the end of the pane, with a
hover highlight honoring focus dim and saturation. Restores the
one-shot monitor's capture-box nil-out so cancelled drags don't leak
the monitor.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
azooz2003-bit added a commit to manaflow-ai/cmux that referenced this pull request Jul 6, 2026
Picks up manaflow-ai/bonsplit#159 round 2:
header drag-out via shared drag-state helper, drop-in append with hover
highlight, cancelled-drag monitor leak fix.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
Tests/BonsplitTests/BonsplitTests.swift (1)

3917-3956: 📐 Maintainability & Code Quality | 🔵 Trivial

Consider extracting shared window/hosting-view setup for render helpers.

renderedFullWidthHeaderIndicatorSaturation and renderedFullWidthPaneChromeAlpha duplicate the same ~20-line NSWindow/NSHostingView/layout-settle boilerplate already present in renderedTabBarIndicatorSaturation and renderedPaneContainerHasTabBar. Extracting a shared helper (e.g., taking a root SwiftUI view and returning the configured hostingView) would reduce duplication as more full-width rendering tests are added.

Also applies to: 4661-4716

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@Tests/BonsplitTests/BonsplitTests.swift` around lines 3917 - 3956, The render
helper in renderedFullWidthHeaderIndicatorSaturation duplicates the same
NSWindow/NSHostingView setup used by renderedFullWidthPaneChromeAlpha,
renderedTabBarIndicatorSaturation, and renderedPaneContainerHasTabBar. Extract
the shared window/hosting-view/layout boilerplate into a common helper that
accepts the root SwiftUI view (or similar) and returns the configured hosting
view, then update these helpers to call it and keep only their unique sampling
logic.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@Tests/BonsplitTests/BonsplitTests.swift`:
- Around line 3917-3956: The render helper in
renderedFullWidthHeaderIndicatorSaturation duplicates the same
NSWindow/NSHostingView setup used by renderedFullWidthPaneChromeAlpha,
renderedTabBarIndicatorSaturation, and renderedPaneContainerHasTabBar. Extract
the shared window/hosting-view/layout boilerplate into a common helper that
accepts the root SwiftUI view (or similar) and returns the configured hosting
view, then update these helpers to call it and keep only their unique sampling
logic.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: f487c4ed-8797-4fc3-8973-7bd179c65be7

📥 Commits

Reviewing files that changed from the base of the PR and between 2c44eea and a83a09c.

📒 Files selected for processing (6)
  • Sources/Bonsplit/Internal/Views/FullWidthTabHeaderView.swift
  • Sources/Bonsplit/Internal/Views/PaneContainerView.swift
  • Sources/Bonsplit/Internal/Views/TabBarView.swift
  • Sources/Bonsplit/Internal/Views/TabItemView.swift
  • Sources/Bonsplit/Public/BonsplitController.swift
  • Tests/BonsplitTests/BonsplitTests.swift
🚧 Files skipped from review as they are similar to previous changes (5)
  • Sources/Bonsplit/Internal/Views/TabItemView.swift
  • Sources/Bonsplit/Internal/Views/PaneContainerView.swift
  • Sources/Bonsplit/Public/BonsplitController.swift
  • Sources/Bonsplit/Internal/Views/TabBarView.swift
  • Sources/Bonsplit/Internal/Views/FullWidthTabHeaderView.swift

@azooz2003-bit
azooz2003-bit merged commit 679ffcf into main Jul 7, 2026
5 checks passed
@azooz2003-bit
azooz2003-bit deleted the feat-pane-full-width-tab-header branch July 7, 2026 19:18
azooz2003-bit added a commit to manaflow-ai/cmux that referenced this pull request Jul 7, 2026
* Add per-pane Full Width Tab mode (palette + tab context menu)

Pane-level analog of pane zoom for single-tab workflows: toggling Full
Width Tab makes the bonsplit pane header show a prominent full-width
title of the selected tab instead of the tab strip. Exposed via the
command palette (palette.toggleFullWidthTab, en+ja) and the tab context
menu; no keyboard shortcut in this pass. State lives per pane in
bonsplit and persists across restarts via
SessionPaneLayoutSnapshot.isFullWidthTabMode (additive optional field,
legacy snapshots decode unchanged). Logic lives in
Workspace+FullWidthTab.swift with a thin delegate case in
Workspace.swift; TabManager.toggleFocusedFullWidthTab mirrors the zoom
helper. Pins vendor/bonsplit to the header/API change
(manaflow-ai/bonsplit#159).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* Bump vendor/bonsplit: full-width header tab drag and drop

Picks up manaflow-ai/bonsplit#159 round 2:
header drag-out via shared drag-state helper, drop-in append with hover
highlight, cancelled-drag monitor leak fix.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* Bump vendor/bonsplit to merged full-width header

* Use Swift Testing for full width tab tests

* Expose full width tab toggle via tab action

* Split full width tab action test fake

* Preserve full width tab toggle success semantics

* Use normal tab chrome for full-width tabs

* Report full width tab toggle failures

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
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.

1 participant