Skip to content

feat(tui): add plus button to session tab bar - #41887

Merged
kitlangton merged 2 commits into
v2from
tui-tab-plus
Aug 12, 2026
Merged

feat(tui): add plus button to session tab bar#41887
kitlangton merged 2 commits into
v2from
tui-tab-plus

Conversation

@kitlangton

@kitlangton kitlangton commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

What

Adds a plus affordance to the session tab bar so a new tab can be opened with the mouse, matching browser tab strips. Previously the only way to open a new tab was the session.new command or navigating home via keybinds.

The plus and the temporary new-session tab are one control with two states: a subdued + affordance that promotes in place into the active new-session slot when clicked, then demotes back (or becomes a real numbered tab once a prompt is submitted). There is never a separate pseudo tab plus a redundant + at the same time.

  • Horizontal strip: a subdued + sits at the end of the strip (hover lifts it like a tab). Clicking it grows the slot into the active tab — bold + New session on the selected background, with the + glyph where the number would be, and a close × on hover. While promoted, the trailing plus is hidden. On submit, the slot becomes a real numbered tab and a fresh + reappears after it.
  • Vertical rail: a + New session row renders below the tab list. Same promotion in place: bold, blue +, selected background, hover close ×. Real tabs never share the rail with a "New session" pseudo tab anymore.
  • Opening carries the current session's location so the new session lands in the same project, exactly like the session.new command.

How

  • packages/tui/src/context/session-tabs.tsx — new add() action on the session-tabs context: navigates home with the current session's location, falling back to location.ref. Same semantics as the session.new command in app.tsx.
  • packages/tui/src/component/session-tabs.tsx — optional add on SessionTabsController.
    • Horizontal: the promoted NEW_SESSION_TAB still joins the adaptive layout as the active tab (so the existing width-growth animation carries the + stretching into the tab), but renders + in the number cell; showPlus() hides the trailing affordance while promoted and drops its ADD_TAB_WIDTH (3) reservation.
    • Vertical: the pseudo tab is gone from the list entirely; the affordance row itself renders the promoted state (newTab()), and the rail scrolls its bottom into view while promoted.
  • packages/tui/src/feature-plugins/system/storybook/session-tabs.tsx — storybook controller wires add to the existing fixture add-tab logic (shared with the t keybind).

Flow

flowchart LR
    idle["subdued + affordance"] -->|click| promoted["slot promotes in place:\nbold + New session, selected bg"]
    promoted -->|submit prompt| real["real numbered tab"]
    real --> idle2["fresh + appears after it"]
    promoted -->|close × / switch away| idle
Loading

Scope

  • No new keybind: session.new already covers keyboard access; this is mouse parity for the tab strip.
  • Follow-ups discussed but not in this PR: reviving the title wipe animation for background title updates, and dimming the placeholder title on not-yet-named sessions.

Testing

  • bun typecheck (packages/tui) clean.
  • bun run test (packages/tui): 642 pass, 0 fail.
  • New test: add opens the new session tab carrying the current session's location in test/context/session-tabs.test.tsx.
  • Manually verified both orientations in a real PTY via terminal-control: idle affordance, hover, promotion on click, and the promoted slot rendering with no second + anywhere.

Demo

OpenCode Drive recording (simulated LLM): a session starts from the promoted new-session slot, the + is clicked and promotes into the active tab, a second session starts there, and clicking tab 1 switches back — the slot demotes to the subdued +.

tab-plus-demo-v2.mp4

@kitlangton
kitlangton merged commit 99166f7 into v2 Aug 12, 2026
12 of 14 checks passed
@kitlangton
kitlangton deleted the tui-tab-plus branch August 12, 2026 02:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant