Motion
Lottie
The lottie-react player, exported as-is, for the Lottie animations that ship with Crew OS (animations/*.json).
Guidelines#
Use it for small illustrative loops: an empty state, an onboarding step, a success tick. The files available here are ai-collaboration, check, cost-deduction, database, demolishing, dollar, filter, flash, girl-avatar, graduate, schedule, timer, trash, trend-arrow, users-team-profile, young-boy-avatar, young-boy-avatar-2 and zap (../../assets/Animations/<name>.json).
What you provide: animationData (the parsed JSON, required), loop (default true), autoplay (default true), className/style for size, and optionally lottieRef, onComplete, initialSegment. The useLottie hook and LottiePlayer type come from lottie-react.
Anatomy: the player renders an SVG that fills its box; size the wrapper (the preview uses 112px). The files carry their own fixed colours, drawn for light backgrounds, so on dark themes place them on a light surface (as here) or pick a file that reads on dark.
Behaviour: plays the file's own timeline. Neither the player nor the files check reduced motion: pass autoplay={false} (or loop={false}) when the user asks for less motion.
Don't use several looping animations in one view, block the page on loading a large JSON (fetch it lazily), or use Lottie where a Lucide icon would do.
Facts#
| Group | Motion |
|---|---|
| Product | Crew OS |
| Global | window.DigitalCrew.Lottie |
| Source | digitalcrew-orchestrator: lottie-react |
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;
var files = ["ai-collaboration", "schedule", "trend-arrow", "users-team-profile", "check", "zap"];
function Tile(p) {
var s = React.useState(null), failed = React.useState(false);
React.useEffect(function () {
fetch("../../assets/Animations/" + p.name + ".json").then(function (r) { if (!r.ok) throw new Error(r.status); return r.json(); })
.then(function (d) { s[1](d); }).catch(function () { failed[1](true); });
}, [p.name]);
return h("figure", { className: "grid justify-items-center gap-2 rounded-xl border bg-card p-3" },
h("div", { className: "flex h-28 w-full items-center justify-center rounded-lg bg-white" },
s[0] ? h(DC.Lottie, { animationData: s[0], loop: true, autoplay: true, className: "size-28" })
: h("span", { className: "text-xs text-neutral-500" }, failed[0] ? "Could not load" : "Loading…")),
h("figcaption", { className: "text-muted-foreground font-mono text-xs" }, p.name + ".json"));
}
function App() {
return h("div", { className: "grid grid-cols-3 gap-3" }, files.map(function (f) { return h(Tile, { key: f, name: f }); }));
}
ReactDOM.createRoot(document.getElementById("root")).render(h(DC.TooltipProvider, { delayDuration: 80 }, h(App)));
})();
</script>