diff --git a/README.md b/README.md index d2443d7..dec86e2 100644 --- a/README.md +++ b/README.md @@ -389,8 +389,8 @@ getPageQuery: ({limit, start, dir, settled}) => ({ The `limit` passed to `getPageQuery` comes from the page size: about three viewports' worth of rows at `estimateSize`, but never below the `minPageSize` -floor (default 100). The floor is sized for short rows; for tall rows (cards, -comments) 100 rows is many viewports of content, so the floor dominates the +floor (default 50). The floor is sized for short rows; for tall rows (cards, +comments) 50 rows is many viewports of content, so the floor dominates the formula and each page load renders far more DOM than needed — showing up as long tasks when a page lands mid-scroll. Lower it so page size tracks the viewport again: diff --git a/demo/react/e2e/seed-test.ts b/demo/react/e2e/seed-test.ts index f010b9f..72904b4 100644 --- a/demo/react/e2e/seed-test.ts +++ b/demo/react/e2e/seed-test.ts @@ -24,7 +24,7 @@ export type TestItem = { // created ASC → Test Item 011 (created = BASE−190H, lowest) // // The 200 items also give the virtualizer enough rows to exercise paging -// (the min page size in the demo is 100). +// (the min page size in the demo is 50). const NAMED: TestItem[] = [ { id: 'tstitem001', diff --git a/demo/react/e2e/tests/app.spec.ts b/demo/react/e2e/tests/app.spec.ts index f3d8254..dba1bb9 100644 --- a/demo/react/e2e/tests/app.spec.ts +++ b/demo/react/e2e/tests/app.spec.ts @@ -14,7 +14,7 @@ test.describe('App', () => { test('shows the correct item count', async ({page}) => { // The virtualizer lazy-loads pages, so the initial count may be an - // estimate of the first page only (e.g. "(~100)"). Just verify that + // estimate of the first page only (e.g. "(~50)"). Just verify that // some item count is displayed in the heading. await expect(page.getByText(/\(~?\d+\)/)).toBeVisible({timeout: 15_000}); }); diff --git a/demo/react/e2e/tests/scroll.spec.ts b/demo/react/e2e/tests/scroll.spec.ts index 859e271..3a135ce 100644 --- a/demo/react/e2e/tests/scroll.spec.ts +++ b/demo/react/e2e/tests/scroll.spec.ts @@ -41,7 +41,7 @@ async function waitForScrollStatePersisted(page: Page) { // The virtual list renders only the visible rows. Scrolling causes new pages // to be fetched and new rows to be inserted into the DOM. With 200 items and a -// min page size of 100, there are at least 2 pages to load. +// min page size of 50, there are at least 2 pages to load. test.describe('Scroll / paging', () => { test.beforeEach(async ({page}) => { @@ -50,7 +50,7 @@ test.describe('Scroll / paging', () => { test('initial render shows the correct item count', async ({page}) => { // The virtualizer lazy-loads pages, so the initial count is an estimate - // based on the first page only (e.g. "(~100)"). Verify a count appears. + // based on the first page only (e.g. "(~50)"). Verify a count appears. await expect(page.getByText(/\(~?\d+\)/)).toBeVisible({timeout: TIMEOUT}); }); @@ -61,14 +61,17 @@ test.describe('Scroll / paging', () => { // The virtualizer lazy-loads pages, so we need to scroll to the bottom // repeatedly — each scroll triggers loading the next page, which extends - // the scrollable area. + // the scrollable area. The per-attempt check is kept short so the retry + // loop gets enough scroll rounds to walk every page (200 items over a + // 50-row min page size), rather than burning the budget on a few long + // waits. await expect(async () => { await viewportEl.evaluate(el => { el.scrollTop = el.scrollHeight; }); await expect( page.locator(`a[href="#${TEST_ITEMS[TEST_ITEMS.length - 1].id}"]`), - ).toBeVisible(); + ).toBeVisible({timeout: 1_000}); }).toPass({timeout: TIMEOUT}); }); diff --git a/src/core/virtualizer.dom.test.ts b/src/core/virtualizer.dom.test.ts index e9d6a25..2975a23 100644 --- a/src/core/virtualizer.dom.test.ts +++ b/src/core/virtualizer.dom.test.ts @@ -110,6 +110,10 @@ function createHarness({ getRowKey: row => row.id, listContextParams: 'ctx', anchoring: 'native', + // Pinned so the paging expectations below (page lengths, anchor indices, + // spaceBefore) stay fixed to a 100-row page rather than tracking the + // minPageSize default. + minPageSize: 100, observeElementRect: (_instance, cb) => { cb({width: 300, height: viewportHeight}); }, diff --git a/src/core/virtualizer.test.ts b/src/core/virtualizer.test.ts index b3fb207..e72d200 100644 --- a/src/core/virtualizer.test.ts +++ b/src/core/virtualizer.test.ts @@ -411,9 +411,9 @@ describe('ZeroVirtualizer wrapper contract', () => { }); describe('minPageSize', () => { - test('defaults the query page size to 100', () => { + test('defaults the query page size to 50', () => { const v = new ZeroVirtualizer(makeOptions()); - expect(v.getQueryInputs().pageSize).toBe(100); + expect(v.getQueryInputs().pageSize).toBe(50); }); test('lowers the floor for tall rows', () => { diff --git a/src/core/virtualizer.ts b/src/core/virtualizer.ts index 267352e..79225c5 100644 --- a/src/core/virtualizer.ts +++ b/src/core/virtualizer.ts @@ -26,7 +26,7 @@ import type { } from './types.ts'; // Make sure this is even since we half it for scroll state loading -const MIN_PAGE_SIZE = 100; +const MIN_PAGE_SIZE = 50; const NUM_ROWS_FOR_LOADING_SKELETON = 1; @@ -122,8 +122,8 @@ export type VirtualizerOptions = { /** * Floor for the query page size. The page size is derived from the viewport * (about three viewports' worth of rows at `estimateSize`), but never drops - * below this floor. Defaults to 100 — sized for short rows; lower it for - * tall rows (cards, comments) where 100 rows is many viewports of content. + * below this floor. Defaults to 50 — sized for short rows; lower it for + * tall rows (cards, comments) where 50 rows is many viewports of content. * Rounded up to an even number (paging halves pages around permalinks). */ minPageSize?: number | undefined; diff --git a/src/solid/create-zero-virtualizer.test.ts b/src/solid/create-zero-virtualizer.test.ts index 085cd8c..f8d86ab 100644 --- a/src/solid/create-zero-virtualizer.test.ts +++ b/src/solid/create-zero-virtualizer.test.ts @@ -163,7 +163,7 @@ describe('createZeroVirtualizer (solid wrapper wiring)', () => { kind: 'forward', startRow: undefined, }); - expect(inputs().pageSize).toBeGreaterThanOrEqual(100); + expect(inputs().pageSize).toBeGreaterThanOrEqual(50); expect(inputs().settled).toBe(false); dispose(); });