UI
Infinite Canvas
A pannable, endless grid of any tiles you like — only on-screen cells mount.
Example.tsx
import { InfiniteCanvas } from "@/components/better/infinite-canvas"import { HouseIcon, UserIcon, BellIcon, HeartIcon, StarIcon } from "@phosphor-icons/react"// items is ReactNode[] — swap these for <img>, <Avatar>, text, whole cards.const icons = [HouseIcon, UserIcon, BellIcon, HeartIcon, StarIcon]export function Example() {return (<InfiniteCanvasclassName="h-80 w-full"cellSize={88}tileSize={56}overscan={1}items={icons.map((Icon, i) => (<Icon key={i} className="size-6" />))}/>)}
Dependencies
Props
| Prop | Type | Default | Description |
|---|---|---|---|
| items* | ReactNode[] | — | The pool of tiles the grid draws from — ANY ReactNode works: icons, images, avatars, text, whole cards. Pass as few or as many as you like; every cell picks one by hashing its coordinates, so the same cell always shows the same tile and neighbours differ. The grid is endless regardless of how many you pass — the items repeat, not the layout. / |
| className | string | — | |
| cellSize | number | 88 | Size of each grid cell (the spacing) in px. |
| tileSize | number | 56 | Size of the tile drawn inside each cell, in px. Must be ≤ cellSize. |
| overscan | number | 1 | Extra ring of cells mounted just outside the viewport. Purely a smoothness/perf trade: higher values pre-mount cells so they're already there when you drag (no pop-in at the edges) at the cost of more DOM. You won't see a difference standing still — only while panning. / |