mirror of
https://github.com/Ark0N/Codeman.git
synced 2026-09-30 12:39:42 +02:00
fix(tabs): re-evaluate auto-wrap on resize and on every full tab rebuild
Review polish on the desktop tab auto-wrap: - Auto-wrap is purely width-driven, but updateTabOverflowMode() was only called at the tail of _renderSessionTabsImmediate (SSE content renders). Window resize — the primary trigger for tabs crossing the one-row overflow threshold — never re-evaluated it, so narrowing/widening the window left the wrap state stale until an unrelated status event fired a render. Call it from the debounced window-resize handler (no-op on mobile/tablet, where the method bails). - Move the re-evaluation into _fullRenderSessionTabs() as well, so the incremental branch's two early `_fullRenderSessionTabs(); return;` paths (badge add/remove, which change tab width) and the manual two-rows toggle (applyTabWrapSettings → _fullRender…) re-evaluate too. The latter also fixes a transient where enabling manual two-rows while auto-wrap was on left both classes set (clipping folder tabs to 96px) until the next render. - Add boundary cases to the policy test: exact fit and the +1 sub-pixel tolerance (no wrap), 2px over (wrap), and a single overflowing tab (no wrap). Verified: tab-overflow test passes; tsc, check:frontend-syntax, check:public-assets, prettier all clean. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -2765,6 +2765,12 @@ class CodemanApp {
|
||||
|
||||
// Update connection lines after tabs change (positions may have shifted)
|
||||
this.updateConnectionLines();
|
||||
|
||||
// Re-evaluate desktop auto-wrap for every full rebuild, including the incremental
|
||||
// branch's early `_fullRenderSessionTabs(); return;` paths and the manual two-rows
|
||||
// toggle (applyTabWrapSettings calls this) which would otherwise leave a stale
|
||||
// tabs-auto-wrap class until the next content render.
|
||||
this.updateTabOverflowMode();
|
||||
}
|
||||
|
||||
// Set up arrow key navigation for session tabs (accessibility)
|
||||
|
||||
@@ -139,6 +139,9 @@ const MobileDetection = {
|
||||
resizeTimeout = setTimeout(() => {
|
||||
this.updateBodyClass();
|
||||
this.updateAppHeight();
|
||||
// Tab auto-wrap is width-driven, so it must re-evaluate on resize — the only
|
||||
// other trigger is a tab content render. No-op on mobile/tablet (method bails).
|
||||
if (typeof app !== 'undefined') app.updateTabOverflowMode?.();
|
||||
}, 100);
|
||||
};
|
||||
window.addEventListener('resize', this._resizeHandler);
|
||||
|
||||
@@ -48,4 +48,18 @@ describe('tab overflow layout policy', () => {
|
||||
})
|
||||
).toBe(false);
|
||||
});
|
||||
|
||||
it('respects the boundary conditions (exact fit, +1 tolerance, and tabCount < 2)', () => {
|
||||
const helper = loadTabOverflowHelper();
|
||||
const base = { deviceType: 'desktop' as const, manualTwoRows: false, tabCount: 6 };
|
||||
|
||||
// Exact fit: no overflow, no wrap.
|
||||
expect(helper.shouldAutoWrapTabs({ ...base, scrollWidth: 800, clientWidth: 800 })).toBe(false);
|
||||
// Within the +1 sub-pixel tolerance: still no wrap.
|
||||
expect(helper.shouldAutoWrapTabs({ ...base, scrollWidth: 801, clientWidth: 800 })).toBe(false);
|
||||
// 2px over: wrap.
|
||||
expect(helper.shouldAutoWrapTabs({ ...base, scrollWidth: 802, clientWidth: 800 })).toBe(true);
|
||||
// A single overflowing tab must not wrap (need at least 2 to form a second row).
|
||||
expect(helper.shouldAutoWrapTabs({ ...base, tabCount: 1, scrollWidth: 1400, clientWidth: 760 })).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user