Lay out a scroll container's content when the content changes
A short list opened after a long one drew all its rows stacked on one point. The fault was not in the list tab: rebuild() handed the row stack to setContent() while it was still empty, so the content was sized to max(rows, viewport) = the viewport. The rows arrived after that, and for a short list the same formula yields the same height, so resize() saw no change and skipped layout(). A long list changes the height and never showed it. relayoutContent() now runs whenever the content changed, rather than leaning on resize()'s change detection - that detection is the wrong instrument for "the children moved". The list tab was the only affected caller: the panels use ListView, which positions its rows itself, and the inspector fills its body before setContent. Also drops the comma line under the list. Every section that can carry a list supplies openList, so the comma fallback in fieldFactory was unreachable; listToText/listFromText go with it. The list-value test now covers coerceListItem through coerceValue instead, so the boolean spelling stays guarded. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
e52e95c0e9
commit
4d07946c74
9 files changed
+102
-87
No files matched your search
@@ -0,0 +1,38 @@
|
||||
import { describe, expect, it } from 'vitest';
|
||||
import { ScrollContainer, Spacer, VStack } from '../../src/ui';
|
||||
|
||||
/** Row tops after a layout; an unlaid-out stack leaves every child at 0. */
|
||||
const tops = (stack: VStack) => stack.children.map((c) => c.y);
|
||||
|
||||
describe('a scroll container told its content changed', () => {
|
||||
it('lays out rows that leave the height pinned to the viewport', () => {
|
||||
const scroll = new ScrollContainer();
|
||||
scroll.resize(200, 300);
|
||||
const rows = new VStack();
|
||||
// The list tab hands over the stack before filling it, so the empty content is measured first
|
||||
// and pinned to the viewport height.
|
||||
scroll.setContent(rows);
|
||||
rows.add(new Spacer(20));
|
||||
rows.add(new Spacer(20));
|
||||
rows.add(new Spacer(20));
|
||||
|
||||
// 60 < 300, so the content keeps the height it already had: `resize` alone would see no
|
||||
// change and skip the layout, leaving all three rows stacked at the top.
|
||||
scroll.relayoutContent();
|
||||
expect(tops(rows)).toEqual([0, 20, 40]);
|
||||
});
|
||||
|
||||
it('still lays out rows that make the content taller than the viewport', () => {
|
||||
const scroll = new ScrollContainer();
|
||||
scroll.resize(200, 50);
|
||||
const rows = new VStack();
|
||||
scroll.setContent(rows);
|
||||
rows.add(new Spacer(20));
|
||||
rows.add(new Spacer(20));
|
||||
rows.add(new Spacer(20));
|
||||
|
||||
scroll.relayoutContent();
|
||||
expect(tops(rows)).toEqual([0, 20, 40]);
|
||||
expect(scroll.maxScroll).toBe(10);
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user