Skip to content

Commit ef88f2f

Browse files
elirantutiaclaude
andcommitted
fix active tab hidden in the tab strip's horizontal overflow
render() rebuilds #tab-list with innerHTML = '', which clamps scrollLeft back to 0, so with enough tabs to overflow the strip the active one silently landed off-screen — most visibly right after clicking a project, since setActiveProject emits project-changed and the tab bar re-renders on it. Capture the offset before the wipe, restore it after the rebuild, then scroll the active tab into view. Restoring it is what keeps unrelated re-renders (unread transitions, share state, layout) from moving the strip at all: with the offset back in place, inline: 'nearest' is a no-op while the tab is already fully visible. The active element is captured in the existing append loop rather than re-queried, since render() already computes isActive. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
1 parent 23541c7 commit ef88f2f

1 file changed

Lines changed: 12 additions & 0 deletions

File tree

‎src/renderer/components/tab-bar/tab-list.ts‎

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -293,10 +293,13 @@ function showTabContextMenu(x: number, y: number, project: ProjectRecord, sessio
293293

294294
export function render(): void {
295295
if (tabListEl.querySelector('.tab-name input')) return;
296+
// Read before the wipe below clamps it to 0.
297+
const prevScrollLeft = tabListEl.scrollLeft;
296298
tabListEl.innerHTML = '';
297299
const project = appState.activeProject;
298300
if (!project) return;
299301

302+
let activeTab: HTMLElement | null = null;
300303
for (const session of project.sessions) {
301304
const tab = document.createElement('div');
302305
const isActive = session.id === project.activeSessionId;
@@ -409,8 +412,17 @@ export function render(): void {
409412
});
410413
});
411414

415+
if (isActive) activeTab = tab;
412416
tabListEl.appendChild(tab);
413417
}
418+
419+
// The rebuild above reset the scroll offset, so put it back and then pull the
420+
// active tab into view — with enough tabs to overflow the strip it otherwise
421+
// stays hidden, most visibly right after switching projects. 'nearest' is a
422+
// no-op while the tab is already fully visible, so restoring the offset is
423+
// what keeps an unrelated re-render from moving the strip at all.
424+
tabListEl.scrollLeft = prevScrollLeft;
425+
activeTab?.scrollIntoView({ block: 'nearest', inline: 'nearest' });
414426
}
415427

416428
// Surgically update a single tab's status dot + tooltip without a full re-render.

0 commit comments

Comments
 (0)