A slowly turning toy shelf — 5–8 chunky plastic-toy product icons rotate around the headline like collectibles on a display stand. Hover a toy to bring it forward; click to navigate.
import CarouselOfProductToys from '@crazygl/hero-carousel-of-product-toys';
export default function Hero() {
return (
<CarouselOfProductToys
heading={"All your\nfavourite tools."}
subheading="Hover one of the toys to bring it forward."
toy1Label="Inbox"
toy1Emoji="💌"
onToy1Click="/inbox"
onToy2Click={(e) => console.log('Tasks clicked', e)}
/>
);
}toyCount (3–8), rotationSpeed (auto-drift, pauses on hover), hoverScale, turntableTilt, pointerParallax.toy{N}Label, toy{N}Color, toy{N}Emoji, toy{N}Shape (cylinder / capsule / cone / box), and onToy{N}Click — one prop that takes either a URL string (from the customizer) or a function (in code), type-detected at runtime.confettiCount drifting sparkle particles (0 disables).bgTop / bgBottom pastel gradient, transparentBackground to drop the backdrop.npm install @crazygl/hero-carousel-of-product-toysThe component takes the same props you see in the live customizer on the right — every default ships poster-quality.
import CarouselOfProductToys from '@crazygl/hero-carousel-of-product-toys';
export default function Landing() {
return (
<CarouselOfProductToys />
);
}The wrapper renders static HTML on the server and only initialises the canvas after hydration, so search engines see your copy.
// app/page.tsx — works in SSR-first frameworks (Next, Remix, Astro, etc.)
'use client';
import CarouselOfProductToys from '@crazygl/hero-carousel-of-product-toys';
export default function Page() {
return (
<section>
<CarouselOfProductToys
heading="Say hi."
subheading="Your new hero."
/>
<article>
<h2>Welcome</h2>
<p>Your content keeps its own voice below the hero.</p>
</article>
</section>
);
}