mirror of
https://github.com/Ark0N/Codeman.git
synced 2026-10-10 01:09:43 +02:00
fix(tabs): wrap case clusters box by box and never route a lineage line through a tab
With tabArrangement 'case' at 1440px (nine tabs in four cases), the lineage routes ran horizontally through the middle of tabs, cluster labels and box borders. #538's clusters are `max-width: 100%` boxes that may shrink, so in the one-line strip every box squeezed and wrapped inside itself (a one-tab case's swatch alone on a line above its tab). The strip then never overflowed, so updateTabOverflowMode() never wrapped it, and #544's routing room (`.lineage-tree.tabs-auto-wrap`: row gap and spine channel) never applied. computeLineageRows grouped the squeezed tabs by top alone into rows that overlap (10-40, 20-50, 42-74), and gapUnder put the first row's gap at y 30, inside the tabs below it. - On the desktop header strip a cluster keeps its width, so clusters that do not fit overflow and the strip wraps box by box; the boxes' own gaps read --lineage-row-gap, so the routes run between box rows and through the spine channel. A case wider than the whole strip still wraps inside its box, and now wraps the strip too (`_tabClustersWrapInside`, the new `innerWrap` input of shouldAutoWrapTabs), so its inner rows get the gap. - computeLineageRows never returns overlapping rows: tabs whose spans overlap are one row. gapUnder returns null when there is no real gap, and a route with no gap is not drawn. A final pass drops any route with a segment inside a tab, so no arrangement can draw a line through a tab (a layout without the room loses lines instead). Pinned with the squeezed rects measured live. At 1920px, where the clusters fit on one line, nothing changes. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -78,6 +78,22 @@ describe('tab overflow layout policy', () => {
|
||||
// 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);
|
||||
});
|
||||
|
||||
it('wraps a strip whose case cluster already wraps inside itself, though nothing overflows', () => {
|
||||
// A case wider than the whole strip is capped at its width and wraps in its
|
||||
// box, so the strip has rows that scrollWidth never shows. Without the wrap,
|
||||
// the lineage routing room (row gap, spine channel) is never reserved.
|
||||
const helper = loadTabOverflowHelper();
|
||||
const fits = { manualTwoRows: false, tabCount: 12, scrollWidth: 800, clientWidth: 800 };
|
||||
|
||||
expect(helper.shouldAutoWrapTabs({ ...fits, deviceType: 'desktop', innerWrap: true })).toBe(true);
|
||||
expect(helper.shouldAutoWrapTabs({ ...fits, deviceType: 'desktop', innerWrap: false })).toBe(false);
|
||||
// The other guards still win.
|
||||
expect(helper.shouldAutoWrapTabs({ ...fits, deviceType: 'tablet', innerWrap: true })).toBe(false);
|
||||
expect(helper.shouldAutoWrapTabs({ ...fits, deviceType: 'desktop', manualTwoRows: true, innerWrap: true })).toBe(
|
||||
false
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
// Issue #257: the phone tab strip scrolls horizontally, so the active tab can
|
||||
|
||||
Reference in New Issue
Block a user