Motion
SkeletonReveal
A skeleton that cross-blurs into the loaded content, so the swap reads as one motion (.t-skel).
Guidelines#
What you provide: a .t-skel wrapper with a fixed height holding .t-skel-skeleton (add is-pulsing to pulse its children) and .t-skel-content; add is-revealed when data arrives. To replay, add is-resetting, force a reflow, then remove it.
Timing: 400ms (--reveal-dur), ease-in-out, 2px blur (--reveal-blur); the pulse is 1s to 50% opacity. Reduced motion swaps instantly.
Use it for records and cards whose shape is known before the data. Shape the skeleton like the content.
Facts#
| Group | Motion |
|---|---|
| Product | Crew OS and Max |
| Kind | Showcase page (tokens and patterns, not a single export) |
| Source | : app/transitions.css |
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;
function App() {
var s = React.useState(false), r = React.useState(false), ref = React.useRef(null);
function replay() { r[1](true); s[1](false); requestAnimationFrame(function () { if (ref.current) void ref.current.offsetWidth; r[1](false); setTimeout(function () { s[1](true); }, 900); }); }
React.useEffect(function () { var t = setTimeout(function () { s[1](true); }, 900); return function () { clearTimeout(t); }; }, []);
return h("div", { className: "grid gap-3" },
h("div", { ref: ref, className: "t-skel h-20 max-w-md" + (s[0] ? " is-revealed" : "") + (r[0] ? " is-resetting" : "") },
h("div", { className: "t-skel-skeleton is-pulsing flex items-center gap-3" },
h("div", { className: "size-12 rounded-full bg-accent" }),
h("div", { className: "grid flex-1 gap-2" }, h("div", { className: "h-4 w-2/3 rounded bg-accent" }), h("div", { className: "h-4 w-1/2 rounded bg-accent" }))),
h("div", { className: "t-skel-content flex items-center gap-3" },
h(DC.ProspectAvatar, { name: "Claire Dubois", size: "md" }),
h("div", { className: "grid" }, h("span", { className: "font-medium" }, "Claire Dubois"), h("span", { className: "text-sm text-muted-foreground" }, "CFO · Northwind Traders · Paris")))),
h(DC.Button, { size: "sm", variant: "outline", className: "w-fit", onClick: replay }, "Replay"));
}
ReactDOM.createRoot(document.getElementById("root")).render(h(DC.TooltipProvider, { delayDuration: 80 }, h(App)));
})();
</script>