mirror of
https://github.com/Ark0N/Codeman.git
synced 2026-11-14 10:39:32 +01:00
fix: cap the first tab on every pass, before a selection widens it (#748)
selectSession() toggles .active at once while _syncTabStripCorner() only runs in the debounced render, so a cap set after measuring left a newly selected first tab wider than the room and dropped the first row below the toolbar until then. max-width changes nothing on a narrower tab, so the cap is simply always on, and the clear-before-measure and finish-the-animation loops go. The no-usable-room test uses 8 tabs: at 40 the scroll fallback fires first and it passed at any threshold. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
823013226d
commit
d9d6fad698
4 files changed
+24
-19
No files matched your search
+7
-12
@@ -7073,8 +7073,6 @@ class CodemanApp {
|
||||
const contentTop = strip.top + parseFloat(style.paddingTop);
|
||||
const contentLeft = strip.left + container.clientLeft + parseFloat(style.paddingLeft);
|
||||
const contentRight = strip.left + container.clientLeft + container.clientWidth - parseFloat(style.paddingRight);
|
||||
// A first tab that cannot fit beside the toolbar would drop the whole first
|
||||
// line below it and leave an empty band: keep the plain strip instead.
|
||||
// The first tab must fit beside the toolbar, or the whole first line drops
|
||||
// below it and leaves an empty band. A selected tab is wider (gear and
|
||||
// close show), so falling back to the plain strip here made the layout
|
||||
@@ -7090,17 +7088,14 @@ class CodemanApp {
|
||||
return;
|
||||
}
|
||||
const firstTab = container.querySelector(':scope > .session-tab');
|
||||
// Cleared first, the first tab's included: the last pass's trim would
|
||||
// otherwise be measured as its width, and a room that grew would untrim a
|
||||
// tab still too wide for it.
|
||||
for (const tab of container.querySelectorAll(':scope > .tab-corner-fit')) tab.classList.remove('tab-corner-fit');
|
||||
// A selection change slides the gear and close open or shut (a width
|
||||
// transition), and this runs in the same render: finish the first tab's
|
||||
// slide, or it is judged by the width it is leaving.
|
||||
for (const anim of firstTab?.getAnimations?.({ subtree: true }) ?? []) {
|
||||
if (/^(width|padding)/.test(anim.transitionProperty ?? '')) anim.finish();
|
||||
// Capped every time, not only once it measures too wide: selectSession()
|
||||
// widens a newly selected tab at once and this pass is debounced, so a cap
|
||||
// set only here afterwards would leave the first row below the toolbar until
|
||||
// it runs. The cap changes nothing on a tab narrower than the room.
|
||||
for (const tab of container.querySelectorAll(':scope > .tab-corner-fit')) {
|
||||
if (tab !== firstTab) tab.classList.remove('tab-corner-fit');
|
||||
}
|
||||
if (firstTab && firstTab.offsetWidth > room) firstTab.classList.add('tab-corner-fit');
|
||||
firstTab?.classList.add('tab-corner-fit');
|
||||
if (container.style.getPropertyValue('--tab-corner-first-max') !== `${room}px`) {
|
||||
container.style.setProperty('--tab-corner-first-max', `${room}px`);
|
||||
}
|
||||
|
||||
@@ -651,9 +651,9 @@ body {
|
||||
margin: 0 2px var(--lineage-row-gap, 4px) 0;
|
||||
}
|
||||
|
||||
/* A first tab wider than the room beside the toolbar (a selected one shows its
|
||||
gear and close) has its name trimmed to fit, so the layout never depends on
|
||||
which tab is selected. */
|
||||
/* The first tab is capped to the room beside the toolbar: one wider than that (a
|
||||
selected one shows its gear and close) has its name trimmed to fit, so the
|
||||
layout never depends on which tab is selected. */
|
||||
.session-tabs-host > .session-tabs.tabs-corner > .session-tab.tab-corner-fit {
|
||||
max-width: var(--tab-corner-first-max, none);
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user