Skip to content

feat(tabs): rename a tab (#212) - #213

Merged
kipavy merged 3 commits into
devfrom
feat/tab-rename
Sep 7, 2026
Merged

feat(tabs): rename a tab (#212)#213
kipavy merged 3 commits into
devfrom
feat/tab-rename

Conversation

@kipavy

@kipavy kipavy commented Sep 7, 2026

Copy link
Copy Markdown
Contributor

Closes #212.

A tab can carry a user-chosen name instead of always showing the connection it opened.

What

  • TerminalSession.title? and SplitTab.name?, both optional. src/utils/sessionLabel.ts owns the fallback: the name the user gave, else the connection name. A split tab without a name keeps deriving its label from the active pane.
  • Edited in place: double-click the label, or Rename… from the tab context menu and the pane-header menu (Rename tab… on a split tab). Enter and blur commit, Escape cancels, an emptied field clears the name and the tab falls back to its connection.
  • Entry points follow the rule settled in feat(tabs): split-tab context menu, and stop an open menu swallowing the next right-click #211 — tab menu is tab scope, anything per-session stays on the pane header.

Persistence

Device-local, by design.

  • title rides the workspace snapshot (SnapshotSession + workspaceRestore), so a rename survives a restart. Additive, so SNAPSHOT_VERSION stays 1 and old snapshots still parse. SplitTab.name needed no snapshot work — layout.splitTabs is stored opaque.
  • It also rides the live-session manifest, so co-attaching a shared session on another device inherits the name the origin device gave it. signature() moved into liveSessionManifestCore.manifestSignature and now includes the title, so a rename is published instead of waiting for the next structural change.
  • Not in the settings-sync payload: the snapshot is never uploaded, and a tab name is device-local state like split layout and scroll offset.

Semantics

Reconnect keeps the name; a connection renamed upstream only moves the fallback; duplicates do not inherit and open on the connection name.

Two bugs the live run caught

Driving the real app in a headless container, not jsdom:

  1. The editor was nested in the tab <button>, so WebKit activated the button on Space — typing build logs named the tab "build" and ran logs in the shell. The tab now renders as a plain container while renaming; a structural test asserts the editor has no button ancestor on both tab kinds.
  2. Closing the editor left focus on <body>. New focusSession() is called on commit and on cancel; a split tab focuses its active pane.

Verification

Live, with real mouse and keyboard: single tab (menu + double-click, name containing a space), split tab (menu + double-click + clearing back to the derived label), pane header (menu + double-click + Escape), focus returning to the terminal, and names surviving an app reload. Not verified live: the mobile chip (it displays names; no rename gesture there) and cross-device inheritance, which needs two devices and Pro sync.

Suites: src/stores 71 files / 457 tests, src/utils + src/services 138 / 1181, touched component dirs 20 / 125, i18n parity 9, tsc --noEmit clean. New strings in en/fr/ru/zh.

🤖 Generated with Claude Code

https://claude.ai/code/session_01TJhKVW41tQnPiG1nXP2jFZ

kipavy and others added 3 commits September 7, 2026 13:19
A tab can now carry a user-chosen name instead of always showing the
connection it opened. The name is edited in place — double-click the
label, or "Rename…" from the tab context menu and the pane header menu —
and clearing it returns the tab to the connection name, so a connection
renamed upstream only ever moves the fallback.

A split tab gets a name of its own; without one it keeps deriving its
label from the active pane, as before.

Persistence is device-local: `title` rides the workspace snapshot, so a
rename survives a restart, and it also rides the live-session manifest,
so co-attaching a shared session on another device inherits the name the
origin device gave it. The manifest signature now includes the title, so
a rename is published rather than waiting for the next structural change.
Duplicates do not inherit the name — a duplicate opens on the connection.
…us back

Found by driving the real app: the editor was nested inside the tab
<button>, so WebKit activated the button on Space — the tab took focus,
the editor blurred and committed a half-typed name, and the rest of the
keystrokes went into the terminal. Typing "build logs" left a tab named
"build" and ran `logs` in the shell.

While renaming, the tab now renders as a plain container instead of the
button, so no ancestor claims the keystrokes. A structural test asserts
the editor has no button ancestor, on both tab kinds — the invariant a
jsdom test can check, since it cannot reproduce native activation.

Closing the editor also left focus on <body>, so the user had to click
back into the terminal. Both surfaces now call the new focusSession()
on commit and on cancel — the split tab hands focus to its active pane.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TJhKVW41tQnPiG1nXP2jFZ
Right-click is not findable, so the rename now has a plain-click entry
point: a click on the label of the tab you are already on opens the
editor. A click on a background tab still just switches to it, so the
common gesture is untouched, and the click that ends a drag is ignored.

The pane header follows the same rule, and a click on an unfocused
pane's title now focuses that pane instead of doing nothing — its title
span stops mousedown to keep the header from dragging, so that click had
no effect at all before.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TJhKVW41tQnPiG1nXP2jFZ
@kipavy
kipavy merged commit 9b00789 into dev Sep 7, 2026
4 checks passed
@kipavy
kipavy deleted the feat/tab-rename branch September 7, 2026 14:04
@kipavy kipavy mentioned this pull request Sep 7, 2026
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