Spotlight Grid
Hero-ready card grid with cursor-tracked spotlight, distance-based lift, and premium motion falloff.
Realtime sync
Sub-100ms collaborative updates.
WebSocket edge mesh
Secure by default
Role policies and audit logs built in.
SOC 2 ready controls
Visual analytics
Funnels and cohort insights in one view.
No SQL required
Workflow automations
Trigger actions from events instantly.
40+ native integrations
AI copilots
Context-aware suggestions in every module.
Trained on workspace data
Global edge delivery
Fast responses across all regions.
99.99% uptime target
1"use client";23import * as React from "react";4import { cva, type VariantProps } from "class-variance-authority";5import { cn } from "@/lib/utils";67const gridVariants = cva("relative grid gap-4", {8 variants: {9 columns: {10 2: "grid-cols-1 sm:grid-cols-2",11 3: "grid-cols-1 sm:grid-cols-2 lg:grid-cols-3",12 4: "grid-cols-1 sm:grid-cols-2 lg:grid-cols-4",13 },14 },15 defaultVariants: {16 columns: 3,17 },18});1920const cardVariants = cva(21 "group relative overflow-hidden rounded-xl border bg-card transition-all duration-200 ease-out will-change-transform",22 {23 variants: {24 variant: {25 default: "border-border/60",26 glow: "border-primary/30",27 subtle: "border-border/40 bg-muted/40",28 },29 size: {30 sm: "p-4",31 md: "p-5",32 lg: "p-6",33 },34 },35 defaultVariants: {36 variant: "default",37 size: "md",38 },39 },40);4142export type SpotlightGridItem = {43 title: string;44 description: string;45 meta?: string;46};4748interface SpotlightGridProps49 extends VariantProps<typeof gridVariants>, VariantProps<typeof cardVariants> {50 items: SpotlightGridItem[];51 radius?: number;52 intensity?: number;53 className?: string;54}5556export function SpotlightGrid({57 items,58 columns,59 variant,60 size,61 radius = 200,62 intensity = 0.6,63 className,64}: SpotlightGridProps) {65 const cardRefs = React.useRef<(HTMLDivElement | null)[]>([]);66 const mouse = React.useRef({ x: 0, y: 0 });67 const raf = React.useRef<number | null>(null);6869 const update = React.useCallback(() => {70 cardRefs.current.forEach((card) => {71 if (!card) return;7273 const rect = card.getBoundingClientRect();7475 const x = mouse.current.x - rect.left;76 const y = mouse.current.y - rect.top;7778 const centerX = rect.width / 2;79 const centerY = rect.height / 2;8081 const dx = x - centerX;82 const dy = y - centerY;8384 const dist = Math.sqrt(dx * dx + dy * dy);85 const norm = Math.max(0, 1 - dist / radius);86 let boost = norm * intensity;8788 // Slight boost for hovered card89 if (card.matches(":hover")) {90 boost *= 1.4;91 }9293 card.style.setProperty("--x", `${x}px`);94 card.style.setProperty("--y", `${y}px`);95 card.style.setProperty("--boost", boost.toString());96 });9798 raf.current = requestAnimationFrame(update);99 }, [radius, intensity]);100101 const handleMove = (e: React.MouseEvent<HTMLDivElement>) => {102 mouse.current.x = e.clientX;103 mouse.current.y = e.clientY;104105 if (!raf.current) {106 raf.current = requestAnimationFrame(update);107 }108 };109110 const handleLeave = () => {111 if (raf.current) {112 cancelAnimationFrame(raf.current);113 raf.current = null;114 }115116 cardRefs.current.forEach((card) => {117 if (!card) return;118 card.style.removeProperty("--boost");119 });120 };121122 React.useEffect(() => {123 return () => {124 if (raf.current) cancelAnimationFrame(raf.current);125 };126 }, []);127128 return (129 <div130 onMouseMove={handleMove}131 onMouseLeave={handleLeave}132 className={cn(gridVariants({ columns }), className)}133 >134 {items.map((item, i) => (135 <div136 key={`${item.title}-${i}`}137 ref={(el) => {138 if (el) {139 cardRefs.current[i] = el;140 }141 }}142 className={cn(cardVariants({ variant, size }))}143 style={{144 transform:145 "translateY(calc(var(--boost, 0) * -6px)) scale(calc(1 + var(--boost, 0) * 0.04))",146 boxShadow:147 "0 20px 40px -20px rgba(0,0,0,calc(0.2 + var(--boost, 0) * 0.3))",148 backgroundImage: `149 radial-gradient(150 ${radius}px circle at var(--x, 50%) var(--y, 50%),151 rgba(255,255,255,calc(0.1 + var(--boost, 0) * 0.25)),152 transparent 60%153 )154 `,155 }}156 >157 {/* Glow overlay */}158 <div className="pointer-events-none absolute inset-0 opacity-0 transition-opacity duration-300 group-hover:opacity-100 bg-gradient-to-b from-white/5 to-transparent" />159160 {/* Content */}161 <div className="relative z-10 space-y-2">162 <h3 className="text-sm font-semibold">{item.title}</h3>163 <p className="text-sm text-muted-foreground">{item.description}</p>164 {item.meta && (165 <p className="text-xs text-muted-foreground/80">{item.meta}</p>166 )}167 </div>168 </div>169 ))}170 </div>171 );172}
Realtime sync
Sub-100ms collaborative updates.
WebSocket edge mesh
Secure by default
Role policies and audit logs built in.
SOC 2 ready controls
Visual analytics
Funnels and cohort insights in one view.
No SQL required
Workflow automations
Trigger actions from events instantly.
40+ native integrations
AI copilots
Context-aware suggestions in every module.
Trained on workspace data
Global edge delivery
Fast responses across all regions.
99.99% uptime target
1"use client";23import * as React from "react";4import { cva, type VariantProps } from "class-variance-authority";5import { cn } from "@/lib/utils";67const gridVariants = cva("relative grid gap-4", {8 variants: {9 columns: {10 2: "grid-cols-1 sm:grid-cols-2",11 3: "grid-cols-1 sm:grid-cols-2 lg:grid-cols-3",12 4: "grid-cols-1 sm:grid-cols-2 lg:grid-cols-4",13 },14 },15 defaultVariants: {16 columns: 3,17 },18});1920const cardVariants = cva(21 "group relative overflow-hidden rounded-xl border bg-card transition-all duration-200 ease-out will-change-transform",22 {23 variants: {24 variant: {25 default: "border-border/60",26 glow: "border-primary/30",27 subtle: "border-border/40 bg-muted/40",28 },29 size: {30 sm: "p-4",31 md: "p-5",32 lg: "p-6",33 },34 },35 defaultVariants: {36 variant: "default",37 size: "md",38 },39 },40);4142export type SpotlightGridItem = {43 title: string;44 description: string;45 meta?: string;46};4748interface SpotlightGridProps49 extends VariantProps<typeof gridVariants>, VariantProps<typeof cardVariants> {50 items: SpotlightGridItem[];51 radius?: number;52 intensity?: number;53 className?: string;54}5556export function SpotlightGrid({57 items,58 columns,59 variant,60 size,61 radius = 200,62 intensity = 0.6,63 className,64}: SpotlightGridProps) {65 const cardRefs = React.useRef<(HTMLDivElement | null)[]>([]);66 const mouse = React.useRef({ x: 0, y: 0 });67 const raf = React.useRef<number | null>(null);6869 const update = React.useCallback(() => {70 cardRefs.current.forEach((card) => {71 if (!card) return;7273 const rect = card.getBoundingClientRect();7475 const x = mouse.current.x - rect.left;76 const y = mouse.current.y - rect.top;7778 const centerX = rect.width / 2;79 const centerY = rect.height / 2;8081 const dx = x - centerX;82 const dy = y - centerY;8384 const dist = Math.sqrt(dx * dx + dy * dy);85 const norm = Math.max(0, 1 - dist / radius);86 let boost = norm * intensity;8788 // Slight boost for hovered card89 if (card.matches(":hover")) {90 boost *= 1.4;91 }9293 card.style.setProperty("--x", `${x}px`);94 card.style.setProperty("--y", `${y}px`);95 card.style.setProperty("--boost", boost.toString());96 });9798 raf.current = requestAnimationFrame(update);99 }, [radius, intensity]);100101 const handleMove = (e: React.MouseEvent<HTMLDivElement>) => {102 mouse.current.x = e.clientX;103 mouse.current.y = e.clientY;104105 if (!raf.current) {106 raf.current = requestAnimationFrame(update);107 }108 };109110 const handleLeave = () => {111 if (raf.current) {112 cancelAnimationFrame(raf.current);113 raf.current = null;114 }115116 cardRefs.current.forEach((card) => {117 if (!card) return;118 card.style.removeProperty("--boost");119 });120 };121122 React.useEffect(() => {123 return () => {124 if (raf.current) cancelAnimationFrame(raf.current);125 };126 }, []);127128 return (129 <div130 onMouseMove={handleMove}131 onMouseLeave={handleLeave}132 className={cn(gridVariants({ columns }), className)}133 >134 {items.map((item, i) => (135 <div136 key={`${item.title}-${i}`}137 ref={(el) => {138 if (el) {139 cardRefs.current[i] = el;140 }141 }}142 className={cn(cardVariants({ variant, size }))}143 style={{144 transform:145 "translateY(calc(var(--boost, 0) * -6px)) scale(calc(1 + var(--boost, 0) * 0.04))",146 boxShadow:147 "0 20px 40px -20px rgba(0,0,0,calc(0.2 + var(--boost, 0) * 0.3))",148 backgroundImage: `149 radial-gradient(150 ${radius}px circle at var(--x, 50%) var(--y, 50%),151 rgba(255,255,255,calc(0.1 + var(--boost, 0) * 0.25)),152 transparent 60%153 )154 `,155 }}156 >157 {/* Glow overlay */}158 <div className="pointer-events-none absolute inset-0 opacity-0 transition-opacity duration-300 group-hover:opacity-100 bg-gradient-to-b from-white/5 to-transparent" />159160 {/* Content */}161 <div className="relative z-10 space-y-2">162 <h3 className="text-sm font-semibold">{item.title}</h3>163 <p className="text-sm text-muted-foreground">{item.description}</p>164 {item.meta && (165 <p className="text-xs text-muted-foreground/80">{item.meta}</p>166 )}167 </div>168 </div>169 ))}170 </div>171 );172}
Deploy pipeline
5 stages passing
Avg 3m 42s
Error tracking
2 unresolved issues
Last seen 4m ago
Incident SLA
99.95% this month
Target 99.9%
API latency
P95 at 126ms
Global avg
1"use client";23import * as React from "react";4import { cva, type VariantProps } from "class-variance-authority";5import { cn } from "@/lib/utils";67const gridVariants = cva("relative grid gap-4", {8 variants: {9 columns: {10 2: "grid-cols-1 sm:grid-cols-2",11 3: "grid-cols-1 sm:grid-cols-2 lg:grid-cols-3",12 4: "grid-cols-1 sm:grid-cols-2 lg:grid-cols-4",13 },14 },15 defaultVariants: {16 columns: 3,17 },18});1920const cardVariants = cva(21 "group relative overflow-hidden rounded-xl border bg-card transition-all duration-200 ease-out will-change-transform",22 {23 variants: {24 variant: {25 default: "border-border/60",26 glow: "border-primary/30",27 subtle: "border-border/40 bg-muted/40",28 },29 size: {30 sm: "p-4",31 md: "p-5",32 lg: "p-6",33 },34 },35 defaultVariants: {36 variant: "default",37 size: "md",38 },39 },40);4142export type SpotlightGridItem = {43 title: string;44 description: string;45 meta?: string;46};4748interface SpotlightGridProps49 extends VariantProps<typeof gridVariants>, VariantProps<typeof cardVariants> {50 items: SpotlightGridItem[];51 radius?: number;52 intensity?: number;53 className?: string;54}5556export function SpotlightGrid({57 items,58 columns,59 variant,60 size,61 radius = 200,62 intensity = 0.6,63 className,64}: SpotlightGridProps) {65 const cardRefs = React.useRef<(HTMLDivElement | null)[]>([]);66 const mouse = React.useRef({ x: 0, y: 0 });67 const raf = React.useRef<number | null>(null);6869 const update = React.useCallback(() => {70 cardRefs.current.forEach((card) => {71 if (!card) return;7273 const rect = card.getBoundingClientRect();7475 const x = mouse.current.x - rect.left;76 const y = mouse.current.y - rect.top;7778 const centerX = rect.width / 2;79 const centerY = rect.height / 2;8081 const dx = x - centerX;82 const dy = y - centerY;8384 const dist = Math.sqrt(dx * dx + dy * dy);85 const norm = Math.max(0, 1 - dist / radius);86 let boost = norm * intensity;8788 // Slight boost for hovered card89 if (card.matches(":hover")) {90 boost *= 1.4;91 }9293 card.style.setProperty("--x", `${x}px`);94 card.style.setProperty("--y", `${y}px`);95 card.style.setProperty("--boost", boost.toString());96 });9798 raf.current = requestAnimationFrame(update);99 }, [radius, intensity]);100101 const handleMove = (e: React.MouseEvent<HTMLDivElement>) => {102 mouse.current.x = e.clientX;103 mouse.current.y = e.clientY;104105 if (!raf.current) {106 raf.current = requestAnimationFrame(update);107 }108 };109110 const handleLeave = () => {111 if (raf.current) {112 cancelAnimationFrame(raf.current);113 raf.current = null;114 }115116 cardRefs.current.forEach((card) => {117 if (!card) return;118 card.style.removeProperty("--boost");119 });120 };121122 React.useEffect(() => {123 return () => {124 if (raf.current) cancelAnimationFrame(raf.current);125 };126 }, []);127128 return (129 <div130 onMouseMove={handleMove}131 onMouseLeave={handleLeave}132 className={cn(gridVariants({ columns }), className)}133 >134 {items.map((item, i) => (135 <div136 key={`${item.title}-${i}`}137 ref={(el) => {138 if (el) {139 cardRefs.current[i] = el;140 }141 }}142 className={cn(cardVariants({ variant, size }))}143 style={{144 transform:145 "translateY(calc(var(--boost, 0) * -6px)) scale(calc(1 + var(--boost, 0) * 0.04))",146 boxShadow:147 "0 20px 40px -20px rgba(0,0,0,calc(0.2 + var(--boost, 0) * 0.3))",148 backgroundImage: `149 radial-gradient(150 ${radius}px circle at var(--x, 50%) var(--y, 50%),151 rgba(255,255,255,calc(0.1 + var(--boost, 0) * 0.25)),152 transparent 60%153 )154 `,155 }}156 >157 {/* Glow overlay */}158 <div className="pointer-events-none absolute inset-0 opacity-0 transition-opacity duration-300 group-hover:opacity-100 bg-gradient-to-b from-white/5 to-transparent" />159160 {/* Content */}161 <div className="relative z-10 space-y-2">162 <h3 className="text-sm font-semibold">{item.title}</h3>163 <p className="text-sm text-muted-foreground">{item.description}</p>164 {item.meta && (165 <p className="text-xs text-muted-foreground/80">{item.meta}</p>166 )}167 </div>168 </div>169 ))}170 </div>171 );172}
Props
| Name | Type | Default | Description |
|---|---|---|---|
| items | { title: string; description: string; meta?: string }[] | required | Grid cards displayed with spotlight interaction |
| intensity | number | 0.6 | Overall strength of brighten/lift effect |
| radius | number | 250 | Spotlight influence radius in pixels |
| falloff (CVA) | "smooth" | "linear" | "sharp" | "smooth" | Curve for how quickly cards fade from spotlight |
| columns (CVA) | "2" | "3" | "4" | "3" | Responsive column preset for card layout |