shadimage
nexus-labs
componentglowing-effect-cardssource: stale · stale

Glowing Effect Cards

Cursor-reactive glowing border cards with a responsive 2-1-2 layout for refined SaaS sections and dashboards.

npx shadcn add "https://nexus-ui.com/r/glowing-effect-cards.json"
free

This source snapshot is older than our freshness window and couldn't be re-verified just now — it may be outdated.

Where it goes

kanbandashboard-shell

Interaction

cursor-follow

Use cases

dashboard

Tags auto-generated by rules on 9/24/2026 — empty means no evidence, not lack of support.

Dependencies

Bundle weight · medium
animationframer-motion
iconslucide-react

Registry dependencies

https://www.nexus-ui.com/api/registry/nexus-fontutils

Files4 · source cached 10/8/2026, 4:46:31 AM

next-ui/glowing-effect-cards/GlowingCard.tsx
"use client";

import * as React from "react";
import { ArrowUpRight } from "lucide-react";
import { cn } from "@/lib/utils";
import { GlowingEffect } from "./GlowingEffect";

export type GlowingCardProps = {
  title: string;
  description: string;
  icon?: React.ReactNode;
  className?: string;
  tall?: boolean;
  cta?: string;
};

export function GlowingCard({
  title,
  description,
  icon,
  className,
  tall = false,
  cta,
}: GlowingCardProps) {
  return (
    <GlowingEffect
      className={cn(
        "h-full rounded-2xl",
        tall ? "min-h-[220px] lg:min-h-full" : "min-h-[210px]",
        className,
      )}
      borderRadius="1rem"
      intensity={1}
      blur={16}
    >
      <div className={cn("flex h-full flex-col justify-between p-5", tall && "lg:p-6")}>
        <div className="space-y-3">
          {icon ? (
            <span className="inline-flex size-10 items-center justify-center rounded-xl border border-border/70 bg-primary/10 text-primary">
              {icon}
            </span>
          ) : null}
          <h3 className="text-lg font-semibold tracking-tight text-foreground dark:text-zinc-100">{title}</h3>
          <p className="text-sm leading-relaxed text-muted-foreground">{description}</p>
        </div>
        {cta ? (
          <span className="mt-5 inline-flex items-center gap-1.5 text-sm font-medium text-primary">
            {cta}
            <ArrowUpRight className="size-3.5" />
          </span>
        ) : null}
      </div>
    </GlowingEffect>
  );
}
next-ui/glowing-effect-cards/GlowingCardsLayout.tsx
"use client";

import * as React from "react";
import { BarChart3, Layers3, ShieldCheck, Sparkles, Workflow } from "lucide-react";
import { cn } from "@/lib/utils";
import { GlowingCard } from "./GlowingCard";

export function GlowingCardsLayout({ className }: { className?: string }) {
  return (
    <section className={cn("mx-auto w-full max-w-6xl", className)}>
      <p className="mb-3 text-center text-xs font-medium uppercase tracking-[0.2em] text-primary/85">
        Hover over the cards to see the magic.
      </p>
      <div className="grid grid-cols-1 gap-4 lg:grid-cols-[minmax(0,1fr)_240px_minmax(0,1fr)] lg:grid-rows-2">
        <GlowingCard
          icon={<Sparkles className="size-4" />}
          title="Interface polish"
          description="Ship refined interactions with futuristic borders that react to every cursor movement."
          cta="View components"
          className="lg:aspect-square"
        />

        <GlowingCard
          icon={<BarChart3 className="size-4" />}
          title="Decision cockpit"
          description="Consolidate metrics, alerts, and status signals in one premium card experience."
          cta="Open dashboard"
          className="lg:col-start-1 lg:row-start-2 lg:aspect-square"
        />

        <GlowingCard
          icon={<Workflow className="size-4" />}
          title="Control rail"
          description="A tall center card that anchors your layout and keeps critical actions in focus."
          cta="Manage flow"
          tall
          className="lg:col-start-2 lg:row-span-2 lg:row-start-1 lg:w-[240px]"
        />

        <GlowingCard
          icon={<ShieldCheck className="size-4" />}
          title="Security confidence"
          description="Communicate trust with clear hierarchy, subtle glow, and clean dark-mode readability."
          cta="Review policy"
          className="lg:col-start-3 lg:row-start-1 lg:aspect-square"
        />

        <GlowingCard
          icon={<Layers3 className="size-4" />}
          title="Composable systems"
          description="Mix reusable card blocks across pricing, feature sections, and product showcases."
          cta="See templates"
          className="lg:col-start-3 lg:row-start-2 lg:aspect-square"
        />
      </div>
    </section>
  );
}
next-ui/glowing-effect-cards/GlowingEffect.tsx
"use client";

import * as React from "react";
import { motion, useMotionTemplate, useMotionValue, useReducedMotion } from "framer-motion";
import { cn } from "@/lib/utils";

export type GlowingEffectProps = {
  children: React.ReactNode;
  className?: string;
  glowColor?: string;
  borderRadius?: string;
  disabled?: boolean;
  intensity?: number;
  blur?: number;
};

const clamp = (value: number, min: number, max: number) => Math.max(min, Math.min(max, value));

export function GlowingEffect({
  children,
  className,
  glowColor = "#7dd3fc",
  borderRadius = "1rem",
  disabled = false,
  intensity = 1,
  blur = 18,
}: GlowingEffectProps) {
  const reduceMotion = useReducedMotion() === true;
  const containerRef = React.useRef<HTMLDivElement | null>(null);
  const x = useMotionValue(0);
  const y = useMotionValue(0);
  const [active, setActive] = React.useState(false);

  const safeIntensity = clamp(intensity, 0.45, 2.4);
  const safeBlur = Math.max(0, blur);

  const borderGlow = useMotionTemplate`radial-gradient(${170 * safeIntensity}px circle at ${x}px ${y}px, #7dd3fc 0%, transparent 70%),
    radial-gradient(${150 * safeIntensity}px circle at calc(${x}px + 30px) calc(${y}px - 20px), #a78bfa 0%, transparent 72%),
    radial-gradient(${140 * safeIntensity}px circle at calc(${x}px - 34px) calc(${y}px + 16px), #f472b6 0%, transparent 74%)`;
  const ambientGlow = useMotionTemplate`radial-gradient(${250 * safeIntensity}px circle at ${x}px ${y}px, #7dd3fc22 0%, transparent 72%),
    radial-gradient(${220 * safeIntensity}px circle at calc(${x}px + 34px) calc(${y}px - 24px), #a78bfa1f 0%, transparent 74%),
    radial-gradient(${210 * safeIntensity}px circle at calc(${x}px - 32px) calc(${y}px + 18px), #f472b61c 0%, transparent 74%)`;

  function updatePointer(clientX: number, clientY: number) {
    if (!containerRef.current) return;
    const rect = containerRef.current.getBoundingClientRect();
    x.set(clientX - rect.left);
    y.set(clientY - rect.top);
  }

  function onPointerMove(e: React.PointerEvent<HTMLDivElement>) {
    if (disabled || reduceMotion) return;
    if (!active) setActive(true);
    updatePointer(e.clientX, e.clientY);
  }

  function onEnter(e: React.PointerEvent<HTMLDivElement>) {
    if (disabled) return;
    setActive(true);
    updatePointer(e.clientX, e.clientY);
  }

  function onLeave() {
    setActive(false);
  }

  return (
    <motion.div
      ref={containerRef}
      className={cn(
        "group relative isolate overflow-hidden border-2 border-white/20 bg-card/95",
        className,
      )}
      style={{ borderRadius }}
      onPointerMove={onPointerMove}
      onPointerEnter={onEnter}
      onPointerLeave={onLeave}
      onFocus={() => !disabled && setActive(true)}
      onBlur={() => setActive(false)}
      animate={disabled ? { y: 0 } : { y: active ? -2 : 0 }}
      transition={{ duration: reduceMotion ? 0.1 : 0.2, ease: "easeOut" }}
      tabIndex={0}
    >
      {!disabled ? (
        <>
          <motion.div
            aria-hidden
            className="pointer-events-none absolute -inset-px rounded-[inherit]"
            style={{
              boxShadow:
                `0 0 ${18 * safeIntensity}px #7dd3fc, ` +
                `0 0 ${24 * safeIntensity}px #a78bfa, ` +
                `0 0 ${32 * safeIntensity}px #f472b6`,
              opacity: active ? 0.95 : 0,
            }}
            transition={{ duration: 0.2 }}
          />
          <motion.div
            aria-hidden
            className="pointer-events-none absolute inset-0 rounded-[inherit]"
            style={{
              backgroundImage: ambientGlow,
              opacity: active ? clamp(0.18 * safeIntensity, 0, 0.35) : 0,
              filter: `blur(${safeBlur * 0.9}px)`,
            }}
            transition={{ duration: 0.2 }}
          />
          <motion.div
            aria-hidden
            className="pointer-events-none absolute inset-0 rounded-[inherit] p-[2px]"
            style={{
              backgroundImage: borderGlow,
              opacity: active ? clamp(1.35 * safeIntensity, 0, 1) : 0,
              filter:
                `drop-shadow(0 0 ${12 * safeIntensity}px #7dd3fc)` +
                ` drop-shadow(0 0 ${10 * safeIntensity}px #a78bfa)` +
                ` drop-shadow(0 0 ${8 * safeIntensity}px #f472b6)`,
            }}
            transition={{ duration: 0.2 }}
          />
        </>
      ) : null}

      <div className="pointer-events-none absolute inset-[2px] rounded-[inherit] bg-gradient-to-b from-background/98 to-background/90 dark:from-zinc-950/98 dark:to-zinc-950/92" />
      <div className="relative z-10">{children}</div>
    </motion.div>
  );
}
next-ui/glowing-effect-cards/index.ts
export type { GlowingEffectProps } from "./GlowingEffect";
export { GlowingEffect } from "./GlowingEffect";
export type { GlowingCardProps } from "./GlowingCard";
export { GlowingCard } from "./GlowingCard";
export { GlowingCardsLayout } from "./GlowingCardsLayout";

More from nexus-labs

Browse all components in this library →