Files
pulse/components/dashboard/VirtualList.tsx
Usman Baig f10b903a80 perf: add export loading state and virtual scrolling for large lists
Export modal now shows a loading indicator and doesn't freeze the UI.
Large list modals use virtual scrolling for smooth performance.
2026-03-10 20:45:49 +01:00

54 lines
1.5 KiB
TypeScript

'use client'
import { useRef } from 'react'
import { useVirtualizer } from '@tanstack/react-virtual'
interface VirtualListProps<T> {
items: T[]
estimateSize: number
className?: string
renderItem: (item: T, index: number) => React.ReactNode
}
export default function VirtualList<T>({ items, estimateSize, className, renderItem }: VirtualListProps<T>) {
const parentRef = useRef<HTMLDivElement>(null)
const virtualizer = useVirtualizer({
count: items.length,
getScrollElement: () => parentRef.current,
estimateSize: () => estimateSize,
overscan: 10,
})
// For small lists (< 50 items), render directly without virtualization
if (items.length < 50) {
return (
<div className={className}>
{items.map((item, index) => renderItem(item, index))}
</div>
)
}
return (
<div ref={parentRef} className={className} style={{ overflow: 'auto' }}>
<div style={{ height: `${virtualizer.getTotalSize()}px`, width: '100%', position: 'relative' }}>
{virtualizer.getVirtualItems().map((virtualRow) => (
<div
key={virtualRow.key}
style={{
position: 'absolute',
top: 0,
left: 0,
width: '100%',
height: `${virtualRow.size}px`,
transform: `translateY(${virtualRow.start}px)`,
}}
>
{renderItem(items[virtualRow.index], virtualRow.index)}
</div>
))}
</div>
</div>
)
}