InfiniteMenu
infinite-menuNavigates an endless spherical menu of image-linked items.
Usage
Basic usage
items are evenly arranged around the sphere and can be dragged and rotated; the item facing the camera is the active item, and its title/description is displayed on the overlay. When image is omitted, the card displays the first character of the title.
Overview
Project global view
<div
className="relative h-80 overflow-hidden rounded-xl"
style={{ background: "oklch(0.16 0.02 255)" }}
>
<InfiniteMenu
items={[
{ title: "Overview", description: "Project Global View" },
{ title: "Task", description: "Workflow in progress" },
{ title: "Members", description: "Team and Permissions" },
]}
/>
</div>Enlarge the sphere · Large card
scale zooms in on the sphere, itemSize zooms in on the single card diameter.
Overview
Project global view
<InfiniteMenu items={items} scale={1.15} itemSize={104} />Turn off auto-rotation
autoRotate={0} Turn off spin, the sphere only rotates when dragged.
Overview
Project global view
<InfiniteMenu items={items} autoRotate={0} />When to use
Use InfiniteMenu to turn navigation or gallery entries into an exploratory draggable sphere on a creative home page or portfolio. Use FlyingPosters for a scrolling poster corridor, or TiltedCard for a single 3D-tilting card.
Import
import { InfiniteMenu } from "@hulianui/ui"Props
| Name | Type | Default | Description |
|---|---|---|---|
| items | InfiniteMenuItem[] | [] | Items distributed with a Fibonacci sphere. The front item becomes active; an empty array renders a placeholder sphere. |
| scale | number | 1 | Sphere scale. Larger values bring larger cards closer. |
| itemSize | number | 88 | Item diameter in pixels. |
| autoRotate | number | 6 | Y-axis rotation in degrees per second. Zero disables it; reduced motion forces zero. |
| className | string | — | Class name forwarded to the root. |
| style | CSSProperties | — | Inline styles forwarded to the root. |
Events
| Event | Type | Description |
|---|---|---|
| onActiveItemChange | (item: InfiniteMenuItem, index: number) => void | Called after drag snapping selects the front item. |
| onItemActivate | (item: InfiniteMenuItem, index: number) => void | false | Called from the active action. Return false to prevent the default window.open. |
InfiniteMenuItem is { image?: string; title?: string; description?: string; link?: string }. An HTTP link opens in a new tab; other links are left to onItemActivate. Without an image, the title's first character is shown.
Usage notes
- The host needs explicit dimensions because sphere geometry is measured from it.
- Non-HTTP links do not navigate automatically; handle them with
onItemActivate, for example withrouter.push. - The component uses CSS 3D and RAF. Reduced motion disables auto-rotation; use a real browser to verify interaction states.
- The action label is built from
"\u6253\u5f00 "(“Open ”) plus the active title, or falls back to"\u6253\u5f00\u6fc0\u6d3b\u9879"(“Open active item”). Placeholder titles use"\u83dc\u5355\u9879 N"(“Menu item N”) and descriptions use"\u5360\u4f4d\u9879 \u00b7 \u4f20\u5165 items \u66ff\u6362"(“Placeholder · pass items to replace”).
Related
Table · Book3D · ProTable · PricingTable · JsonViewer · EditableTable
Playground
Overview
Project global view
<div className="relative h-80 overflow-hidden rounded-xl"
style={{ background: "oklch(0.16 0.02 255)" }}>
<InfiniteMenu
items={items}
scale={1}
itemSize={88}
autoRotate={6}
/>
</div>