Component reference
VirtualList
Search a large directory without mounting every visible record at once.
Preview
Live previewOptional six-digit hex. Clear to restore the preset. Check contrast with your brand color.
Changes apply to this preview only.
Team directory
2,000 people · search re-renders the window, not the list
2000 matching member(s)
Amélie Bernard
Design
Lucas Moreau
Engineering
Sofia Rossi
Engineering
Jean Dupont
Design
Marie Laurent
Engineering
Nicolas Martin
Engineering
Sophie Bernard
Design
Amélie Moreau
Engineering
Width adapts to the available space
"use client";
import {
Card,
CardHeader,
CardTitle,
CardDescription,
CardContent,
Input,
VirtualList,
Avatar,
Badge
} from "@pimolu/react";
import { useState } from "react";
const firstNames = [
"Amélie",
"Lucas",
"Sofia",
"Jean",
"Marie",
"Nicolas",
"Sophie",
];
const lastNames = [
"Bernard",
"Moreau",
"Rossi",
"Dupont",
"Laurent",
"Martin",
];
const members = Array.from(
{ length: 2000 },
(_, index) => ({
id: `member-${index}`,
name: `${firstNames[index % firstNames.length]} ${lastNames[index % lastNames.length]}`,
team: index % 3 === 0 ? "Design" : "Engineering",
})
);
export function DemoExample() {
const [query, setQuery] = useState("");
const filteredMembers = query.trim()
? members.filter((member) => member.name
.toLowerCase()
.includes(query.trim().toLowerCase()))
: members;
return (
<Card>
<CardHeader>
<CardTitle>Team directory</CardTitle>
<CardDescription>
2,000 people · search re-renders the window, not the list
</CardDescription>
</CardHeader>
<CardContent>
<div className="grid gap-5 min-w-0">
<Input
label="Search people"
placeholder="Type a name"
value={query}
clearable
onValueChange={setQuery}
helperText={`${filteredMembers.length} matching member(s)`}
/>
{
filteredMembers.length > 0
? (<VirtualList
items={filteredMembers}
itemHeight={52}
height={300}
overscan={2}
aria-label="Team directory"
getKey={(member) => member.id}
renderItem={(member) => (<div
style={{
display: "flex",
alignItems: "center",
gap: 12,
height: "100%",
padding: "0 12px",
borderBottom: "1px solid var(--pimolu-border)",
boxSizing: "border-box",
}}
>
<Avatar name={member.name} size="sm" />
<div
style={{
minWidth: 0,
flex: 1,
}}
>
<p style={{ margin: 0 }}>
{member.name}
</p>
<p className="text-sm text-muted leading-relaxed">
{member.team}
</p>
</div>
<Badge variant="secondary">
{member.team}
</Badge>
</div>)}
/>)
: (<p className="text-sm text-muted">
No member matches “{query}”.
</p>)
}
</div>
</CardContent>
</Card>
);
}More examples
Different configurations and compositions using the real Pimolu API. Each preview runs independently and follows the site appearance.
Audit log
10,000 events at a fixed 56 px row height with three rows of overscan. The spacer keeps the real scrollbar length.
50,000 log lines
A 50,000 log lines composition using VirtualList.
Compact rows
A compact rows composition using VirtualList.
Usage
Keep item identities and estimated dimensions stable; virtualization changes which rows exist in the DOM.
API reference
Generated from the public TypeScript declarations. Native HTML attributes are inherited where the component extends them; this reference includes Pimolu props and selected common native attributes.
PimoluVirtualListItemsProps
Type source| Name | Type | Default | Description |
|---|---|---|---|
itemsRequired | readonly T[] | — | Data source. Its length defines the row count. |
itemCount | undefined | — | Public Pimolu prop; see the source declaration for details. |
renderItemRequired | (item: T, index: number) => ReactNode | — | Renders one item. |
getKey | ((item: T, index: number) => Key) | undefined | — | Stable React key for a row. Falls back to the index. |
itemHeightRequired | number | — | Fixed height of every row, in pixels. |
heightRequired | number | — | Height of the scroll viewport, in pixels. |
overscan | number | undefined | 3 | Extra rows rendered above and below the viewport. Defaults to 3. |
onChange | ChangeEventHandler<HTMLDivElement, Element> | undefined | — | Standard React/HTML attribute. |
defaultValue | string | number | readonly string[] | undefined | — | Standard React/HTML attribute. |
className | string | undefined | — | Standard React/HTML attribute. |
style | CSSProperties | undefined | — | Standard React/HTML attribute. |
aria-label | string | undefined | — | Defines a string value that labels the current element. |
onClick | MouseEventHandler<HTMLDivElement> | undefined | — | Standard React/HTML attribute. |
itemsRequiredreadonly T[]No default extracted.
Data source. Its length defines the row count.
itemCountundefinedNo default extracted.
Public Pimolu prop; see the source declaration for details.
renderItemRequired(item: T, index: number) => ReactNodeNo default extracted.
Renders one item.
getKey((item: T, index: number) => Key) | undefinedNo default extracted.
Stable React key for a row. Falls back to the index.
itemHeightRequirednumberNo default extracted.
Fixed height of every row, in pixels.
heightRequirednumberNo default extracted.
Height of the scroll viewport, in pixels.
overscannumber | undefinedDefault: 3
Extra rows rendered above and below the viewport. Defaults to 3.
onChangeChangeEventHandler<HTMLDivElement, Element> | undefinedNo default extracted.
Standard React/HTML attribute.
defaultValuestring | number | readonly string[] | undefinedNo default extracted.
Standard React/HTML attribute.
classNamestring | undefinedNo default extracted.
Standard React/HTML attribute.
styleCSSProperties | undefinedNo default extracted.
Standard React/HTML attribute.
aria-labelstring | undefinedNo default extracted.
Defines a string value that labels the current element.
onClickMouseEventHandler<HTMLDivElement> | undefinedNo default extracted.
Standard React/HTML attribute.
PimoluVirtualListCountProps
Type source| Name | Type | Default | Description |
|---|---|---|---|
itemCountRequired | number | — | Row count when there is no item array. |
items | undefined | — | Public Pimolu prop; see the source declaration for details. |
renderItemRequired | (index: number) => ReactNode | — | Renders one row from its index. |
getKey | ((index: number) => Key) | undefined | — | Stable React key for a row. Falls back to the index. |
itemHeightRequired | number | — | Fixed height of every row, in pixels. |
heightRequired | number | — | Height of the scroll viewport, in pixels. |
overscan | number | undefined | 3 | Extra rows rendered above and below the viewport. Defaults to 3. |
onChange | ChangeEventHandler<HTMLDivElement, Element> | undefined | — | Standard React/HTML attribute. |
defaultValue | string | number | readonly string[] | undefined | — | Standard React/HTML attribute. |
className | string | undefined | — | Standard React/HTML attribute. |
style | CSSProperties | undefined | — | Standard React/HTML attribute. |
aria-label | string | undefined | — | Defines a string value that labels the current element. |
onClick | MouseEventHandler<HTMLDivElement> | undefined | — | Standard React/HTML attribute. |
itemCountRequirednumberNo default extracted.
Row count when there is no item array.
itemsundefinedNo default extracted.
Public Pimolu prop; see the source declaration for details.
renderItemRequired(index: number) => ReactNodeNo default extracted.
Renders one row from its index.
getKey((index: number) => Key) | undefinedNo default extracted.
Stable React key for a row. Falls back to the index.
itemHeightRequirednumberNo default extracted.
Fixed height of every row, in pixels.
heightRequirednumberNo default extracted.
Height of the scroll viewport, in pixels.
overscannumber | undefinedDefault: 3
Extra rows rendered above and below the viewport. Defaults to 3.
onChangeChangeEventHandler<HTMLDivElement, Element> | undefinedNo default extracted.
Standard React/HTML attribute.
defaultValuestring | number | readonly string[] | undefinedNo default extracted.
Standard React/HTML attribute.
classNamestring | undefinedNo default extracted.
Standard React/HTML attribute.
styleCSSProperties | undefinedNo default extracted.
Standard React/HTML attribute.
aria-labelstring | undefinedNo default extracted.
Defines a string value that labels the current element.
onClickMouseEventHandler<HTMLDivElement> | undefinedNo default extracted.
Standard React/HTML attribute.
PimoluVirtualListProps
Type source| Name | Type | Default | Description |
|---|---|---|---|
itemCount | number | undefined | — | Row count when there is no item array. |
items | readonly T[] | undefined | — | Data source. Its length defines the row count. |
renderItemRequired | ((index: number) => ReactNode) | ((item: T, index: number) => ReactNode) | — | Renders one row from its index. Renders one item. |
getKey | ((index: number) => Key) | ((item: T, index: number) => Key) | undefined | — | Stable React key for a row. Falls back to the index. |
itemHeightRequired | number | — | Fixed height of every row, in pixels. |
heightRequired | number | — | Height of the scroll viewport, in pixels. |
overscan | number | undefined | 3 | Extra rows rendered above and below the viewport. Defaults to 3. |
onChange | ChangeEventHandler<HTMLDivElement, Element> | undefined | — | Standard React/HTML attribute. |
defaultValue | string | number | readonly string[] | undefined | — | Standard React/HTML attribute. |
className | string | undefined | — | Standard React/HTML attribute. |
style | CSSProperties | undefined | — | Standard React/HTML attribute. |
aria-label | string | undefined | — | Defines a string value that labels the current element. |
onClick | MouseEventHandler<HTMLDivElement> | undefined | — | Standard React/HTML attribute. |
itemCountnumber | undefinedNo default extracted.
Row count when there is no item array.
itemsreadonly T[] | undefinedNo default extracted.
Data source. Its length defines the row count.
renderItemRequired((index: number) => ReactNode) | ((item: T, index: number) => ReactNode)No default extracted.
Renders one row from its index. Renders one item.
getKey((index: number) => Key) | ((item: T, index: number) => Key) | undefinedNo default extracted.
Stable React key for a row. Falls back to the index.
itemHeightRequirednumberNo default extracted.
Fixed height of every row, in pixels.
heightRequirednumberNo default extracted.
Height of the scroll viewport, in pixels.
overscannumber | undefinedDefault: 3
Extra rows rendered above and below the viewport. Defaults to 3.
onChangeChangeEventHandler<HTMLDivElement, Element> | undefinedNo default extracted.
Standard React/HTML attribute.
defaultValuestring | number | readonly string[] | undefinedNo default extracted.
Standard React/HTML attribute.
classNamestring | undefinedNo default extracted.
Standard React/HTML attribute.
styleCSSProperties | undefinedNo default extracted.
Standard React/HTML attribute.
aria-labelstring | undefinedNo default extracted.
Defines a string value that labels the current element.
onClickMouseEventHandler<HTMLDivElement> | undefinedNo default extracted.
Standard React/HTML attribute.
Accessibility
- Verify focus does not disappear on scroll and provide search or another route to offscreen items.