OrbitImages
orbit-imagesMoves child items along preset or custom CSS offset paths with spacing and tilt controls.
Usage
Basic usage
The elliptical orbit is filled with sub-items at equal intervals and surrounds at a constant speed; centerContent stacks the static center.
<OrbitImages
items={images.map((src) => (
<img key={src} src={src} alt="" className="h-full w-full rounded-full object-cover" />
))}
shape="ellipse"
duration={24}
itemSize={48}
showPath
centerContent={<span className="text-sm font-semibold">Hulian</span>}
/>Circular Orbit
shape=circle is equipped with radius to control the circle diameter, and more sub-items are evenly distributed.
<OrbitImages
items={avatars}
shape="circle"
radius={260}
duration={30}
itemSize={44}
/>Star Orbit·Reverse
shape=star takes the star path, direction=reverse lets the children flow in the reverse direction.
<OrbitImages
items={avatars}
shape="star"
radius={300}
duration={28}
itemSize={40}
direction="reverse"
showPath
/>Infinity symbol·Filing away
shape=infinity takes the ∞ path; fill=false lets the children start from the same starting point.
<OrbitImages
items={avatars}
shape="infinity"
radiusX={620}
radiusY={220}
duration={20}
itemSize={44}
fill={false}
showPath
/>When to Use
Use it to circulate avatars, icons, or logos along a shaped track in an ecosystem, partner, or technology-stack display. For simple concentric circular orbits, use OrbitingCircles. OrbitImages supports richer offset-path shapes, arbitrary React nodes, and server rendering without JavaScript dependencies.
Import
import { OrbitImages } from "@hulianui/ui"Props
| Name | Type | Default | Description |
|---|---|---|---|
| shape | "ellipse"|"circle"|"square"|"rectangle"|"triangle"|"star"|"heart"|"infinity"|"wave"|"custom" | "ellipse" | Track preset; set customPath when using "custom" |
| customPath | string | — | SVG path d with shape="custom" (coordinates based on baseWidth square canvas) |
| baseWidth | number | 1400 | Design canvas side length (px·square viewBox), only affects path geometric proportions |
| radiusX | number | 700 | Horizontal radius of ellipse/rectangle/infinity/wave (px·based on baseWidth) |
| radiusY | number | 170 | Vertical radius of ellipse/rectangle/infinity/wave |
| radius | number | 300 | Radius of circle/square/triangle/star/center |
| starPoints | number | 5 | Number of points in the star track |
| starInnerRatio | number | 0.5 | Star inner-to-outer radius ratio (0–1); lower values create sharper points |
| rotation | number | -8 | Orbital inclination angle (deg), the child rotates in the opposite direction to maintain uprightness |
| duration | number | 40 | The time it takes to complete a lap (seconds), the larger it is, the slower it is |
| itemSize | number | 64 | Single child side length (px·CSS pixels) |
| direction | "normal"|"reverse" | "normal" | Flow direction |
| fill | boolean | true | Distributes items evenly when true; starts all items from the same point when false |
| showPath | boolean | false | Trace track path (debug/decoration) |
| pathColor | string | "var(--color-border)" | Track stroke color |
| pathWidth | number | 2 | Track stroke width (px·based on baseWidth) |
| className | string | — | Passthrough to root container |
| style | CSSProperties | — | Inline styles forwarded to the root container, which defaults to a 1:1 aspect ratio and fills the parent width |
Slots
| Slot | Type | Description |
|---|---|---|
| items * | ReactNode[] | Sub-items surrounding the track (img/icon/avatar/card are acceptable), required |
| centerContent | ReactNode | Centered content (Logo/Title), does not rotate with the track |
Usage Guidelines
- Pure CSS
offset-pathdriver, zero dependence on RSC security; however,offset-pathhas compatibility differences in old browsers/some WebKit, and key scenarios need to be verified on a real machine. radiusX/Y/radius/baseWidthare all design pixels in the baseWidth coordinate system, not the final screen pixels - the container is scaled by CSS to fill the parent width, adjust the geometric proportion to change these, and adjust the actual size to change the size of the parent container.pathColoruses semantic colors such asvar(--color-border)with--color-prefix when giving tokens to avoid naked var from not being parsed. See [[hulian-token-color-var-needs-color-prefix]].
Related
BorderBeam · ShineBorder · GlareHover · Lens · AnimatedBeam · OrbitingCircles
Playground
<OrbitImages
items={images.map((src) => (
<img key={src} src={src} alt="" className="h-full w-full rounded-full object-cover" />
))}
shape="ellipse"
duration={24}
itemSize={48}
rotation={-8}
showPath={false}
fill={true}
/>