feat(tabs): rename a tab (#212) - #213
Merged
Merged
Conversation
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
Closed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #212.
A tab can carry a user-chosen name instead of always showing the connection it opened.
What
TerminalSession.title?andSplitTab.name?, both optional.src/utils/sessionLabel.tsowns 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.Persistence
Device-local, by design.
titlerides the workspace snapshot (SnapshotSession+workspaceRestore), so a rename survives a restart. Additive, soSNAPSHOT_VERSIONstays 1 and old snapshots still parse.SplitTab.nameneeded no snapshot work —layout.splitTabsis stored opaque.signature()moved intoliveSessionManifestCore.manifestSignatureand now includes the title, so a rename is published instead of waiting for the next structural change.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:
<button>, so WebKit activated the button on Space — typingbuild logsnamed the tab "build" and ranlogsin 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.<body>. NewfocusSession()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/stores71 files / 457 tests,src/utils+src/services138 / 1181, touched component dirs 20 / 125, i18n parity 9,tsc --noEmitclean. New strings in en/fr/ru/zh.🤖 Generated with Claude Code
https://claude.ai/code/session_01TJhKVW41tQnPiG1nXP2jFZ