Active Foundation · Example
Ten thousand rows of varying height
Ten thousand rows of varying heightClient
0 of 10,000 rows in the DOM
Full source examples/virtual/long-list.tsx
// apps/docs/examples/virtual/long-list.tsx'use client';
import {useState} from 'react';
import {Button} from '@workspace/active-ui/components/primitives/button';import {Input} from '@workspace/active-ui/components/primitives/input';import {Label} from '@workspace/active-ui/components/primitives/label';import {useVirtualAxis} from '@workspace/active-virtual/react';
const COUNT = 10_000;
/** Every seventh row wraps to a second line: the axis measures real heights. */function rowText(position: number): string { const base = `Row ${(position + 1).toLocaleString('en')}`; return position % 7 === 3 ? `${base}: a longer note that wraps to a second line in a narrow column, so this row is taller than its estimate.` : base;}
/** 10,000 rows of varying height; only the rows in view (plus overscan) are in the DOM. */export default function LongList() { const [container, setContainer] = useState<HTMLDivElement | null>(null); const [target, setTarget] = useState('5000'); const {projection, controller, itemRef} = useVirtualAxis({ count: COUNT, estimate: 32, container, }); return ( <div className="flex flex-col gap-3"> <form className="flex flex-wrap items-end gap-2" onSubmit={(event) => { event.preventDefault(); const row = Number(target); if (Number.isInteger(row) && row >= 1 && row <= COUNT) controller.scrollToPosition(row - 1, {align: 'center'}); }} > <div className="flex flex-col gap-1.5"> <Label htmlFor="virtual-target">Row</Label> <Input id="virtual-target" className="w-28" inputMode="numeric" value={target} onChange={(event) => setTarget(event.target.value)} /> </div> <Button type="submit" variant="outline"> Go to row </Button> </form> <div ref={setContainer} className="bg-background h-72 overflow-auto rounded-md border" tabIndex={0} role="region" aria-label="Ten thousand rows" data-virtual-container > <div style={{height: projection.extent, position: 'relative'}}> {projection.items.map((item) => ( <div key={item.identity} ref={itemRef(item.identity)} className="border-b px-3 py-1.5 text-sm" style={{ position: 'absolute', top: 0, left: 0, width: '100%', transform: `translateY(${item.offset}px)`, }} data-position={item.position} > {rowText(item.position)} </div> ))} </div> </div> <p className="text-muted-foreground text-sm" aria-live="polite"> {projection.items.length} of {COUNT.toLocaleString('en')} rows in the DOM </p> </div> );}