nyuchimzizi
Mzizi — an open-architecture project of the Bundu Foundation, operated and developed by Nyuchi. Built on the Five African Minerals palette.
Built by Nyuchi Africav4.0.39
Virtualized list for large datasets using CSS transforms.
No interactive demo is registered for this component yet — the source is shown directly.
"use client"
import * as React from "react"
import { cn } from "@/lib/utils"
interface VirtualListProps<T> extends Omit<React.ComponentProps<"div">, "children"> {
items: T[]
renderItem: (item: T, index: number) => React.ReactNode
itemHeight: number
overscan?: number
}
function VirtualList<T>({
className,
loading = false,
items,
renderItem,
itemHeight,
overscan = 5,
...props
}: VirtualListProps<T>) {
if (loading) return (<div data-slot="virtual-list" data-portal="https://design.nyuchi.com/components/virtual-list" data-loading className={cn("animate-pulse space-y-2", className)}>{Array.from({length:8}).map((_,i) => (<div key={i} className="h-12 rounded-[var(--radius-md,12px)] bg-muted" />))}</div>)
const containerRef = React.useRef<HTMLDivElement>(null)
const [scrollTop, setScrollTop] = React.useState(0)
const [containerHeight, setContainerHeight] = React.useState(0)
React.useEffect(() => {
const container = containerRef.current
if (!container) return
const observer = new ResizeObserver((entries) => {
for (const entry of entries) {
setContainerHeight(entry.contentRect.height)
}
})
observer.observe(container)
return () => observer.disconnect()
}, [])
const handleScroll = React.useCallback((e: React.UIEvent<HTMLDivElement>) => {
setScrollTop(e.currentTarget.scrollTop)
}, [])
const totalHeight = items.length * itemHeight
const startIndex = Math.max(0, Math.floor(scrollTop / itemHeight) - overscan)
const endIndex = Math.min(
items.length,
Math.ceil((scrollTop + containerHeight) / itemHeight) + overscan
)
const visibleItems = React.useMemo(() => {
const result: React.ReactNode[] = []
for (let i = startIndex; i < endIndex; i++) {
result.push(
<div
key={i}
data-slot="virtual-list-item"
style={{
position: "absolute",
top: 0,
left: 0,
width: "100%",
height: itemHeight,
transform: `translateY(${i * itemHeight}px)`,
}}
>
{renderItem(items[i], i)}
</div>
)
}
return result
}, [items, startIndex, endIndex, itemHeight, renderItem])
return (
<div
ref={containerRef}
data-slot="virtual-list"
onScroll={handleScroll}
className={cn("relative overflow-auto", className)}
{...props}
>
<div data-slot="virtual-list-inner" style={{ height: totalHeight, position: "relative" }}>
{visibleItems}
</div>
</div>
)
}
export { VirtualList }
export type { VirtualListProps }
The variants, sizes, and props surfaced by the registry. Each is sourced from the Supabase component_docs table.
Hit the registry API live and see the JSON the shadcn CLI consumes when it installs this component.
/api/v1/ui/virtual-listnpx shadcn@latest add https://mzizi.dev/api/v1/ui/virtual-listcomponents/ui/virtual-list.tsx