Motion
OrbitingCircles
Places its children on a circular orbit around the centre of the parent and spins them, with an optional faint ring for the path.
Guidelines#
Use it for showing integrations or channels circling a product mark. Stack two with different radii and directions for depth.
What you provide: a relative flex items-center justify-center parent with a size, a centre element, and one OrbitingCircles per ring. Props: children (spread evenly around the ring), radius (px, default 160), duration (s per turn, default 20), speed (divides the duration, default 1), reverse, path (draw the ring, default true), iconSize (px box per child, default 30), index and startAnimationDelay (s, stagger the entrance), once (animate in only the first time), className (for the ring).
Anatomy: the ring is a circle of the given radius with a 1px border (rgba(249,250,251,0.07) in dark mode) and a top-down gradient from 5% black (3% white in dark mode) to transparent at 54.76%. Each child sits in a size-[var(--icon-size)] box with 4px padding, rounded-full, z-20; style the child itself.
Behaviour: when the ring enters the viewport it springs in (stiffness 120, damping 18, delay index × 0.2s); children pop in 0.6s later, 0.2s apart. Each child runs the CSS orbit keyframes, linear and infinite. Leaving the viewport unmounts them unless once. No reduced-motion branch.
Don't put more than about six items on one ring, or clickable items on a moving orbit.
Facts#
| Group | Motion |
|---|---|
| Product | Crew OS |
| Global | window.DigitalCrew.OrbitingCircles |
| Source | digitalcrew-orchestrator: components/ui/orbiting-circle.tsx |
| Import in the app | import { OrbitingCircles } from "@/components/ui/orbiting-circle"; |
API#
TypeScript declarations emitted from components/ui/orbiting-circle.tsx.
export interface OrbitingCirclesProps extends HTMLMotionProps<"div"> {
className?: string;
children?: React.ReactNode;
reverse?: boolean;
duration?: number;
delay?: number;
radius?: number;
path?: boolean;
iconSize?: number;
speed?: number;
index?: number;
startAnimationDelay?: number;
once?: boolean;
}
export declare function OrbitingCircles({ className, children, reverse, duration, radius, path, iconSize, speed, index, startAnimationDelay, once, ...props }: OrbitingCirclesProps): any;Example#
The code of the preview above: plain React.createElement against window.DigitalCrew, with realistic data.
<div id="root" class="p-6"></div>
<script>
(function () {
var h = React.createElement, DC = window.DigitalCrew, I = DC.Icons, B = DC.BrandIcons;
function chip(Icon, key, big) { return h("span", { key: key, className: "flex items-center justify-center rounded-full border bg-card shadow-sm " + (big ? "size-9" : "size-8") }, h(Icon, { className: "size-4" })); }
function App() {
return h("div", { className: "relative flex h-72 items-center justify-center overflow-hidden rounded-xl border" },
h("span", { className: "bg-background z-10 flex size-14 items-center justify-center rounded-full border shadow-sm" }, h(B.logo, { className: "size-7 fill-foreground" })),
h(DC.OrbitingCircles, { radius: 64, iconSize: 40, duration: 16 }, chip(I.Mail, "m"), chip(I.Linkedin, "l"), chip(I.Phone, "p")),
h(DC.OrbitingCircles, { radius: 118, iconSize: 44, duration: 28, reverse: true, index: 1 }, chip(I.Calendar, "c", 1), chip(I.Target, "t", 1), chip(I.Users, "u", 1), chip(I.Bot, "b", 1)));
}
ReactDOM.createRoot(document.getElementById("root")).render(h(DC.TooltipProvider, { delayDuration: 80 }, h(App)));
})();
</script>