Docs · Motion, icons and 3D
React Three Fiber
three.js scenes that load only when they're on screen.
The 3D components use three.js 0.186 through React Three Fiber 9, which lets you build scenes as React components. three.js is about 600 KB, so it only loads on pages that show a scene.
Install
pnpm add three @react-three/fiberpnpm add -D @types/threeLoad scenes lazily
Pages import scenes from one entry file that wraps each in next/dynamic with ssr: false. three.js never runs on the server, and a skeleton holds the space while it loads:
src/components/three/index.tsx
"use client"; import dynamic from "next/dynamic";import { Skeleton } from "@/components/ui/skeleton"; /** * Lazy entry points for the 3D components. three.js (~600 KB) loads only when a * scene is on the page, and never on the server. */const loading = () => <Skeleton className="size-full min-h-64 rounded-md" />; export const VaultScene = dynamic( () => import("./vault-scene").then((m) => m.VaultScene), { ssr: false, loading, },); export const PropertyModel = dynamic( () => import("./property-model").then((m) => m.PropertyModel), { ssr: false, loading, },); export const RentBars3D = dynamic( () => import("./rent-bars").then((m) => m.RentBars3D), { ssr: false, loading, },); export type { Unit, UnitStatus } from "./property-model";export type { MonthValue } from "./rent-bars";Using a scene
import { PropertyModel } from "@/components/three"; <PropertyModel name="Riverside Apartments" units={units} />Build a scene
Wrap every scene in Scene. It sets up the canvas, pauses rendering when the scene is off screen, shows a fallback if WebGL isn't available, and takes a text label for screen readers.
spinning-box.tsx
"use client"; import { Scene } from "./scene";import { useThemeColors } from "./use-theme-colors"; export function SpinningBox() { const colors = useThemeColors(); // live token colors; follow the theme return ( <Scene label="A violet box turning slowly" className="h-64"> <ambientLight intensity={0.8} /> <mesh rotation={[0.4, 0.6, 0]}> <boxGeometry /> <meshStandardMaterial color={colors.primary} /> </mesh> </Scene> );}- Color materials with
useThemeColors()so scenes follow light, dark and custom themes. - Give every scene a text label, and show its data some other way too (a list or table), since not everyone can see or use 3D.
- Add new scenes to
src/components/three/index.tsxas lazy exports; never import a scene file directly into a page.