Builder Pattern #
Composable virtual list — pay only for the features you use.
Why Builder Pattern? #
Different use cases need different features. A contact list doesn't need async loading. A photo gallery doesn't need groups. Bundling everything wastes bytes.
| Configuration | Bundle | vs. monolithic |
|---|---|---|
| Base (no features) | 7.7 KB | – |
| + Selection | 10.0 KB | 2.1× smaller |
| + Grid + Scrollbar | 11.7 KB | 1.8× smaller |
| + Groups | 12.3 KB | 1.8× smaller |
| + Async + Page | 13.5 KB | 1.6× smaller |
| All features | ~16 KB | 1.4× smaller |
Traditional virtual lists: 20–23 KB minimum (all features bundled).
The Three Steps #
1. `vlist(config)` — create a builder #
import { vlist } from '@floor/vlist';
const builder = vlist({
container: '#app',
items: data,
item: {
height: 48,
template: (item) => `<div>${item.name}</div>`,
},
});
// builder is NOT a list yet
2. `.use(feature)` — add features #
import { withSelection, withScrollbar } from '@floor/vlist';
builder
.use(withSelection({ mode: 'multiple' }))
.use(withScrollbar({ autoHide: true }));
Each .use() returns the builder, so calls chain. Features auto-sort by internal priority — you don't need to worry about order.
3. `.build()` — get the instance #
const list = vlist({ ... })
.use(withSelection({ mode: 'multiple' }))
.build();
// Now you have a live VList instance
list.scrollToIndex(50);
list.select(1, 2, 3);
list.destroy();
Available Features #
| Feature | Import | Cost | Description |
|---|---|---|---|
withGrid() |
@floor/vlist |
+4.0 KB | 2D grid layout (virtualises by row) |
withGroups() |
@floor/vlist |
+4.6 KB | Grouped lists with sticky or inline headers |
withAsync() |
@floor/vlist |
+5.3 KB | Lazy loading via adapter |
withSelection() |
@floor/vlist |
+2.3 KB | Single / multiple item selection |
withScale() |
@floor/vlist |
+2.2 KB | 1M+ item compression |
withScrollbar() |
@floor/vlist |
+1.0 KB | Custom scrollbar UI |
withPage() |
@floor/vlist |
+0.9 KB | Document-level scrolling |
withSnapshots() |
built-in | 0 KB | Scroll save/restore |
Feature Compatibility #
| Combination | Works? |
|---|---|
withGrid() + withGroups() |
✅ Grouped grid |
withGrid() + withSelection() |
✅ Selectable gallery |
withGroups() + withSelection() |
✅ Selectable grouped list |
withAsync() + withScale() |
✅ Large async dataset |
withPage() + withAsync() |
✅ Infinite scroll feed |
withGrid() + orientation: 'horizontal' |
❌ Grid requires vertical |
withGroups() + orientation: 'horizontal' |
❌ Groups require vertical |
withPage() + withScrollbar() |
❌ Conflicting scroll ownership |
reverse: true + orientation: 'horizontal' |
❌ Reverse requires vertical |
The builder throws at runtime if you combine incompatible features.
Complex Example #
File browser with grouped grid, multi-select, and custom scrollbar:
import {
vlist,
withGrid,
withGroups,
withSelection,
withScrollbar,
} from '@floor/vlist';
const browser = vlist({
container: '#browser',
items: files,
item: {
height: 200,
template: (file, index, { selected }) => `
<div class="file-card ${selected ? 'file-card--selected' : ''}">
<img src="${file.thumbnail}" />
<span>${file.name}</span>
</div>
`,
},
})
.use(withGrid({ columns: 6, gap: 12 }))
.use(withGroups({
getGroupForIndex: (i) => files[i].category,
headerHeight: 40,
headerTemplate: (cat) => `<h2 class="category-header">${cat}</h2>`,
sticky: true,
}))
.use(withSelection({ mode: 'multiple' }))
.use(withScrollbar({ autoHide: true }))
.build();
// Bundle: ~15.3 KB gzipped
browser.on('selection:change', ({ selectedIds }) => {
toolbar.setCount(selectedIds.length);
});
Conditional Features #
Features can be added conditionally before calling .build():
import { vlist, withGrid, withSelection } from '@floor/vlist';
let builder = vlist({
container: '#list',
items: data,
item: { height: 200, template: renderItem },
});
if (config.showGrid) {
builder = builder.use(withGrid({ columns: 4, gap: 16 }));
}
if (config.allowSelection) {
builder = builder.use(withSelection({ mode: 'multiple' }));
}
const list = builder.build();
See Also #
- Quick Start — Copy-paste examples for every use case
- Features Overview — All features with correct API
- Grid · Groups · Async
- Selection · Scale · Scrollbar
- API Reference — Complete method reference