Marketing
FeaturesGridWithGlowingEffect
The five value cards of the Crew OS landing page (cut waste, run lean, always on, reliable by default, shared knowledge), each wrapped in a pointer-following GlowingEffect.
Guidelines#
Use it for the features block, on its own or overlapped by the CPU circuit in CpuSuperposition. It takes no props: titles and descriptions come from the features.items messages (efficiency, costs, scale, delivery, intelligence).
Anatomy: a ul grid, one column, two from sm, four from md, ten from lg with equal row heights; each item spans two columns (five across on desktop). Items are at least 192px tall (224px from md). The shell is rounded-[1rem] (1.25rem from md), 0.75px border-border, 8px padding; the inner card is rounded-lg, 0.75px border, bg-background, 16px padding (20px from md), shadow-sm (a soft 20px glow in dark mode), centred. Icons are 32px Lucide strokes at 1.5 (TrendingDown, Activity, Zap, ShieldCheck, plus a drawn three-node triangle) in text-foreground; titles text-sm md:text-base font-semibold uppercase tracking-wider; descriptions text-xs md:text-sm leading-relaxed text-muted-foreground.
Behaviour: each glow uses spread 30, proximity 50, inactiveZone 0.01, borderWidth 2: it follows the pointer within 50px of a card and does nothing on touch devices. (The preview circles a synthetic pointer until yours moves.)
Don't add a sixth card (the ten-column grid is built for five), or put links inside cards.
Facts#
| Group | Marketing |
|---|---|
| Product | Crew OS |
| Global | window.DigitalCrew.FeaturesGridWithGlowingEffect |
| Source | digitalcrew-orchestrator: components/glowing-effect.tsx |
| Import in the app | import { FeaturesGridWithGlowingEffect } from "@/components/glowing-effect"; |
API#
TypeScript declarations emitted from components/glowing-effect.tsx.
export declare function FeaturesGridWithGlowingEffect(): JSX.Element;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 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() {
var li = ref.current && ref.current.querySelectorAll("li")[2];
if (!live || !li) return;
var r = li.getBoundingClientRect(); t += 0.03;
window.dispatchEvent(new PointerEvent("pointermove", { clientX: r.left + r.width / 2 + Math.cos(t) * (r.width / 2 + 10), clientY: r.top + r.height / 2 + Math.sin(t) * (r.height / 2 + 10), bubbles: true }));
id = requestAnimationFrame(step);
}
id = requestAnimationFrame(step);
return function () { live = false; cancelAnimationFrame(id); window.removeEventListener("pointermove", real); };
}, []);
return h("div", { ref: ref }, h(DC.FeaturesGridWithGlowingEffect));
}
ReactDOM.createRoot(document.getElementById("root")).render(h(DC.TooltipProvider, { delayDuration: 80 }, h(App)));
})();
</script>