Web InnoventixFreeCode

Spotlight hover feature cards

Original · free

A responsive feature card grid where each card follows the cursor with a radial spotlight glow, lifts and rotates its icon on hover, reveals a call to action, and sits above a scrolling logo marquee.

byWeb InnoventixReact + Tailwind
spotlight hover cardscursor glow cardframer motion feature cardshover glow gridanimated feature cardsinteractive card grid
Open

Copy prompt gives Claude Code, Cursor or v0 a ready-to-paste prompt that recreates this exact component.

npx shadcn@latest add https://webinnoventix.com/r/afeature-spotlight-cards.json
afeature-spotlight-cards.tsx
"use client";

import type { ReactNode, MouseEvent } from "react";
import { motion, useMotionValue, useMotionTemplate } from "motion/react";

const cardsReveal = {
  hidden: {},
  show: { transition: { staggerChildren: 0.08, delayChildren: 0.05 } },
};

const cardReveal = {
  hidden: { opacity: 0, y: 28 },
  show: { opacity: 1, y: 0, transition: { type: "spring", stiffness: 120, damping: 18 } },
};

type Feature = { title: string; body: string; icon: ReactNode };

const features: Feature[] = [
  {
    title: "Instant search",
    body: "Type a few letters and results appear before you finish. Everything is indexed on the edge for sub-second answers.",
    icon: (
      <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round" className="h-6 w-6" aria-hidden="true">
        <circle cx="11" cy="11" r="7" /><path d="m20 20-3-3" />
      </svg>
    ),
  },
  {
    title: "Smart automations",
    body: "Set a rule once and let it run. Repetitive steps disappear so your team can focus on the work that matters.",
    icon: (
      <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round" className="h-6 w-6" aria-hidden="true">
        <circle cx="12" cy="12" r="3" /><path d="M12 2v3M12 19v3M2 12h3M19 12h3M5 5l2 2M17 17l2 2M19 5l-2 2M7 17l-2 2" />
      </svg>
    ),
  },
  {
    title: "Live collaboration",
    body: "Cursors, comments and changes sync in real time. Everyone stays on the same page without a single refresh.",
    icon: (
      <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round" className="h-6 w-6" aria-hidden="true">
        <path d="M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2" /><circle cx="9" cy="7" r="4" />
        <path d="M22 21v-2a4 4 0 0 0-3-3.87M16 3.13A4 4 0 0 1 16 11" />
      </svg>
    ),
  },
  {
    title: "Granular permissions",
    body: "Decide exactly who can see and change what. Roles, groups and audit trails keep sensitive work protected.",
    icon: (
      <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round" className="h-6 w-6" aria-hidden="true">
        <rect x="4" y="10" width="16" height="11" rx="2" /><path d="M8 10V7a4 4 0 0 1 8 0v3" />
      </svg>
    ),
  },
  {
    title: "Deep insights",
    body: "Turn raw activity into clear trends. Dashboards refresh continuously so decisions rest on the latest numbers.",
    icon: (
      <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round" className="h-6 w-6" aria-hidden="true">
        <path d="M3 3v18h18" /><path d="m7 14 3-4 3 3 4-6" />
      </svg>
    ),
  },
  {
    title: "Open integrations",
    body: "Connect the tools you already use through a friendly API and webhooks. No workflow gets left behind.",
    icon: (
      <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round" className="h-6 w-6" aria-hidden="true">
        <path d="M10 13a5 5 0 0 0 7 0l3-3a5 5 0 0 0-7-7l-1 1" /><path d="M14 11a5 5 0 0 0-7 0l-3 3a5 5 0 0 0 7 7l1-1" />
      </svg>
    ),
  },
];

const trust = ["Northwind", "Everpeak", "Lumen Co", "Brightwave", "Cobalt", "Meridian", "Foundry", "Skylark"];

function SpotlightCard({ feature }: { feature: Feature }) {
  const mx = useMotionValue(-200);
  const my = useMotionValue(-200);
  const spotlight = useMotionTemplate`radial-gradient(340px circle at ${mx}px ${my}px, rgba(99,102,241,0.16), transparent 70%)`;

  function handleMove(e: MouseEvent<HTMLDivElement>) {
    const rect = e.currentTarget.getBoundingClientRect();
    mx.set(e.clientX - rect.left);
    my.set(e.clientY - rect.top);
  }

  return (
    <motion.div
      variants={cardReveal}
      onMouseMove={handleMove}
      whileHover={{ y: -8 }}
      transition={{ type: "spring", stiffness: 300, damping: 22 }}
      className="group relative overflow-hidden rounded-2xl border border-slate-200/80 bg-white/70 p-6 backdrop-blur-sm transition-colors duration-300 hover:border-indigo-400/60 dark:border-white/10 dark:bg-white/[0.04] dark:hover:border-indigo-400/40"
    >
      <motion.div aria-hidden="true" style={{ background: spotlight }} className="pointer-events-none absolute inset-0 opacity-0 transition-opacity duration-300 group-hover:opacity-100" />
      <div className="relative">
        <motion.span
          whileHover={{ rotate: -6, scale: 1.05 }}
          transition={{ type: "spring", stiffness: 300, damping: 15 }}
          className="inline-flex h-12 w-12 items-center justify-center rounded-xl bg-indigo-500/10 text-indigo-600 ring-1 ring-inset ring-indigo-500/20 dark:text-indigo-300"
        >
          {feature.icon}
        </motion.span>
        <h3 className="mt-5 text-lg font-semibold tracking-tight">{feature.title}</h3>
        <p className="mt-2 text-sm leading-relaxed text-slate-600 dark:text-slate-400">{feature.body}</p>
        <span className="mt-4 inline-flex items-center gap-1 text-sm font-medium text-indigo-600 opacity-0 transition-all duration-300 group-hover:gap-2 group-hover:opacity-100 dark:text-indigo-400">
          Learn more
          <svg viewBox="0 0 20 20" fill="currentColor" className="h-4 w-4" aria-hidden="true">
            <path fillRule="evenodd" d="M3 10a1 1 0 0 1 1-1h9.6l-3.3-3.3a1 1 0 1 1 1.4-1.4l5 5a1 1 0 0 1 0 1.4l-5 5a1 1 0 0 1-1.4-1.4l3.3-3.3H4a1 1 0 0 1-1-1Z" clipRule="evenodd" />
          </svg>
        </span>
      </div>
    </motion.div>
  );
}

export default function SpotlightFeatureCards() {
  return (
    <section className="relative w-full overflow-hidden bg-slate-50 px-5 py-24 text-slate-900 dark:bg-slate-950 dark:text-white sm:px-8">
      <style>{`
        @keyframes spc-marquee { to { transform: translateX(-50%); } }
        .spc-marquee { animation: spc-marquee 24s linear infinite; }
        @media (prefers-reduced-motion: reduce) { .spc-marquee { animation: none !important; } }
      `}</style>

      <div className="pointer-events-none absolute left-1/2 top-10 h-72 w-[38rem] max-w-full -translate-x-1/2 rounded-full bg-fuchsia-300/20 blur-[100px] dark:bg-fuchsia-700/20" />

      <motion.header
        initial={{ opacity: 0, y: 24 }}
        whileInView={{ opacity: 1, y: 0 }}
        viewport={{ once: true, amount: 0.5 }}
        transition={{ duration: 0.6 }}
        className="relative mx-auto max-w-2xl text-center"
      >
        <span className="inline-flex items-center gap-2 rounded-full border border-slate-200 bg-white px-3 py-1 text-xs font-medium text-slate-600 dark:border-white/10 dark:bg-white/5 dark:text-slate-300">
          <span className="h-1.5 w-1.5 rounded-full bg-fuchsia-500" />
          Why teams choose us
        </span>
        <h2 className="mt-5 text-balance text-4xl font-semibold tracking-tight sm:text-5xl">
          Features that carry their weight
        </h2>
        <p className="mx-auto mt-4 max-w-xl text-pretty text-base text-slate-600 dark:text-slate-400">
          Hover any card to light it up. Each one is built to be fast, accessible and genuinely useful.
        </p>
      </motion.header>

      <motion.div
        variants={cardsReveal}
        initial="hidden"
        whileInView="show"
        viewport={{ once: true, amount: 0.15 }}
        className="relative mx-auto mt-14 grid max-w-6xl grid-cols-1 gap-5 sm:grid-cols-2 lg:grid-cols-3"
      >
        {features.map((f) => (
          <SpotlightCard key={f.title} feature={f} />
        ))}
      </motion.div>

      <div className="relative mx-auto mt-16 max-w-6xl">
        <p className="text-center text-xs font-medium uppercase tracking-widest text-slate-400 dark:text-slate-500">Trusted by fast-moving teams</p>
        <div className="mt-6 overflow-hidden [mask-image:linear-gradient(90deg,transparent,#000_12%,#000_88%,transparent)]">
          <div className="spc-marquee flex w-max items-center gap-12">
            {[...trust, ...trust].map((name, i) => (
              <span key={i} className="whitespace-nowrap text-lg font-semibold text-slate-400 dark:text-slate-600">{name}</span>
            ))}
          </div>
        </div>
      </div>
    </section>
  );
}

Dependencies

motion

Licence

Built by Web Innoventix. Free for personal and commercial use, no attribution required.

Built by Web Innoventix

Need a custom interface, a full website, or SEO that gets you cited by AI? We design, build and rank it end to end.

Get a free quote

Similar components

Browse all →
Three Column Icon Grid

Three Column Icon Grid

Original

A responsive icon grid that presents six product capabilities as scannable cards, each with an inline SVG icon, title and short description.

Alternating Media Rows

Alternating Media Rows

Original

Three feature rows that alternate a text column with a CSS-built visual panel, walking the reader through a plan, measure and ship story.

Bento Feature Grid

Bento Feature Grid

Original

A bento-style grid mixing one large hero cell, a tall stat cell and several compact cards to give features a clear visual hierarchy.

Tabbed Feature Switcher

Tabbed Feature Switcher

Original

A tabbed feature preview that switches panels using only native radio inputs and Tailwind peer variants, so it works with no JavaScript.

Stat Backed Features

Stat Backed Features

Original

A feature layout that pairs each capability with a headline metric, so every claim is anchored to a measurable result.

Scroll-reveal bento grid

Scroll-reveal bento grid

Original

An asymmetric bento feature grid whose cards stagger into view on scroll, lift on hover and feature an animated conic gradient border, shimmering headline, growing bar chart and a masked marquee tag strip.

Sticky scroll steps

Sticky scroll steps

Original

A scroll-linked how-it-works section where a sticky panel cross-fades between steps and a progress ring plus filling timeline track advance as you scroll through the process.

Animated marquee highlights band

Animated marquee highlights band

Original

A bold feature band with an animated gradient background, floating blurred orbs, blur-in staggered headline, two opposing marquee pill rows and shimmering stat cards.

Bordered Feature Grid (2x2)

Bordered Feature Grid (2x2)

MIT

A two-column grid of bordered feature cards, each pairing an outlined icon with a title and supporting copy. Clean, enterprise-leaning layout with full dark-mode support.

Outlined Feature Cards with CTA

Outlined Feature Cards with CTA

MIT

A three-column feature section with heading and intro, plus blue-outlined cards that each carry an icon, description, and a circular arrow call-to-action. Fully theme-aware.

Icon-Left Feature List

Icon-Left Feature List

MIT

A centered heading over a three-column feature list, each row leading with a rounded icon badge and a 'Learn More' link. Classic marketing feature block, ported with added dark variants.

Hover-Reveal Bento Grid

Hover-Reveal Bento Grid

MIT

The Magic UI bento pattern: a mixed-span grid of cards where the icon shrinks and the description lifts on hover to reveal a call-to-action. Self-contained (no framer-motion, no icon libs), pure CSS group-hover, with a glow background and full dark styling.