Effects
GlowingEffect
A multicolour glow that runs along a card's border and follows the pointer around it.
Guidelines#
Use it for feature cards on marketing pages (the Crew OS features grid). One grid of glowing cards per page at most.
What you provide: place it as the first child of a relative, rounded card. Props: disabled (default true, which shows only a plain border, so pass false), glow (default false), spread (arc half-width in degrees, default 20), proximity (px outside the card that still counts, default 0), inactiveZone (share of the card's centre that switches the glow off, default 0.7), borderWidth (default 1), blur (default 0), movementDuration (s, default 2), variant (default, white), className. Crew OS uses spread={30} glow disabled={false} proximity={50} inactiveZone={0.01} borderWidth={2} on a rounded-[1rem] border-[0.75px] p-2 shell (1.25rem from md) around a rounded-lg border-[0.75px] bg-background p-4 shadow-sm inner card.
Anatomy: the gradient repeats a conic sweep five times through #dd7bbb, #d79f1e, #5a922c, #4c7894 (the dc-magenta, dc-gold, dc-forest, dc-ocean accents). A conic mask shows only an arc 2 × spread degrees wide, centred on the pointer's angle.
Behaviour: it listens to pointermove on the window. The arc turns to the pointer angle over movementDuration with ease [0.16, 1, 0.3, 1] and fades in and out over 300ms. It does nothing on devices without hover. (The preview drives a synthetic pointer until you move yours.)
Don't forget disabled={false}, or nest it in a card without position: relative.
Facts#
| Group | Effects |
|---|---|
| Product | Crew OS |
| Global | window.DigitalCrew.GlowingEffect |
| Source | digitalcrew-orchestrator: components/ui/glowing-effect.tsx |
| Import in the app | import { GlowingEffect } from "@/components/ui/glowing-effect"; |
API#
TypeScript declarations emitted from components/ui/glowing-effect.tsx.
declare const GlowingEffect: any;
export { GlowingEffect };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 items = [
{ icon: I.Inbox, title: "Inbox triage", text: "Replies sorted by intent before you open your mail." },
{ icon: I.Calendar, title: "Meeting prep", text: "A one-page brief on every prospect, an hour before the call." },
{ icon: I.Send, title: "Follow-ups", text: "No thread goes quiet: nudges go out on day 3 and day 7." }
];
function Card(p) {
return h("div", { className: "relative h-full rounded-[1rem] border-[0.75px] border-border p-2" },
h(DC.GlowingEffect, { spread: 30, glow: true, disabled: false, proximity: 50, inactiveZone: 0.01, borderWidth: 2 }),
h("div", { className: "relative flex h-full flex-col gap-3 overflow-hidden rounded-lg border-[0.75px] bg-background p-4 shadow-sm" },
h(p.icon, { className: "size-6" }),
h("h3", { className: "text-sm font-semibold" }, p.title),
h("p", { className: "text-muted-foreground text-xs leading-relaxed" }, p.text)));
}
function App() {
var ref = React.useRef(null);
React.useEffect(function () {
// Demo only: a synthetic pointer circles the middle card until a real pointer moves.
var t = 0, id = 0, live = true;
function real(e) { if (e.isTrusted) { live = false; window.removeEventListener("pointermove", real); } }
window.addEventListener("pointermove", real);
function step() {
if (!live || !ref.current) return;
var r = ref.current.getBoundingClientRect(); t += 0.03;
var x = r.left + r.width / 2 + Math.cos(t) * (r.width / 2 + 10), y = r.top + r.height / 2 + Math.sin(t) * (r.height / 2 + 10);
window.dispatchEvent(new PointerEvent("pointermove", { clientX: x, clientY: y, bubbles: true }));
id = requestAnimationFrame(step);
}
id = requestAnimationFrame(step);
return function () { live = false; cancelAnimationFrame(id); window.removeEventListener("pointermove", real); };
}, []);
return h("ul", { className: "grid grid-cols-3 gap-4" },
items.map(function (it, i) { return h("li", { key: it.title, ref: i === 1 ? ref : null, className: "min-h-[12rem] list-none" }, h(Card, it)); }));
}
ReactDOM.createRoot(document.getElementById("root")).render(h(DC.TooltipProvider, { delayDuration: 80 }, h(App)));
})();
</script>