game-maker / suite (push) Successful in 9m18s
Nine tabs need 631 px; at 1280x800 the centre column offers 666 px, so the tenth tab would have spilled under the inspector - the same overflow CI caught in run 5. TabStrip replaces the bare HStack: it fits the longest prefix that stays inside the budget, always appends the active tab, and offers the rest behind a fixed 28 px button. The button's width is fixed on purpose - deriving it from the number of hidden tabs would make width depend on the count and the count on the width. The rule itself is a pure function (tabRow.ts), so it is checked without a browser. setActive() calls relayout() itself because Widget.resize only lays out on a changed size, and switching tabs does not change any size. Adding a tab now needs no space arithmetic - only a line in TAB_ORDER, TAB_LABELS and panes, all three Record<CentreTab, ...>, so forgetting one is a type error. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
50 lines
1.7 KiB
TypeScript
50 lines
1.7 KiB
TypeScript
import { describe, expect, it } from 'vitest';
|
|
import { tabRowLayout } from '../../src/editor/tabRow';
|
|
|
|
/** The nine tabs as measured in the browser at padding 4, in their editor order. */
|
|
const TABS = [
|
|
{ key: 'scene', width: 53 },
|
|
{ key: 'game', width: 50 },
|
|
{ key: 'graph', width: 74 },
|
|
{ key: 'statemachine', width: 114 },
|
|
{ key: 'shader', width: 61 },
|
|
{ key: 'texture', width: 64 },
|
|
{ key: 'animation', width: 83 },
|
|
{ key: 'container', width: 81 },
|
|
{ key: 'list', width: 35 },
|
|
];
|
|
|
|
const layout = (available: number, active: string) =>
|
|
tabRowLayout({ tabs: TABS, available, gap: 2, overflowWidth: 28, active });
|
|
|
|
describe('tab row', () => {
|
|
it('hides nothing while the row fits', () => {
|
|
const { shown, hidden } = layout(631, 'scene');
|
|
expect(hidden).toEqual([]);
|
|
expect(shown).toHaveLength(9);
|
|
});
|
|
|
|
it('hides the tail one pixel short of fitting', () => {
|
|
expect(layout(630, 'scene').hidden).toEqual(['list']);
|
|
});
|
|
|
|
it('keeps the tabs in order', () => {
|
|
expect(layout(400, 'scene').shown).toEqual(['scene', 'game', 'graph', 'statemachine', 'shader']);
|
|
});
|
|
|
|
it('shows the active tab even when it sits past the room there is', () => {
|
|
const { shown, hidden } = layout(400, 'container');
|
|
expect(shown).toContain('container');
|
|
expect(hidden).toContain('shader');
|
|
// It went in at the back, so the row still reads left to right.
|
|
expect(shown[shown.length - 1]).toBe('container');
|
|
});
|
|
|
|
it('gives up every other tab before it drops the active one', () => {
|
|
expect(layout(60, 'animation')).toEqual({
|
|
shown: ['animation'],
|
|
hidden: ['scene', 'game', 'graph', 'statemachine', 'shader', 'texture', 'container', 'list'],
|
|
});
|
|
});
|
|
});
|