WebberUI

Spotlight Card

A cursor spotlight card — a border glow and a fainter background bloom track the cursor together and fade out on leave, with each card in a row staying independent.

Loading preview…
npx shadcn@latest add https://webberui.com/r/spotlight-card.json

Playground

Tune the props live — the code snippet updates as you go, so you can dial in the look you want before copying it.

320
<SpotlightCard />

Installation

npx shadcn@latest add https://webberui.com/r/spotlight-card.json

Or, once registries are configured in components.json, install it as @webberui/spotlight-card.

Usage

Put the content straight into children and write the size and layout on className:

import { SpotlightCard } from "@/components/ui/spotlight-card";

<SpotlightCard className="max-w-sm">
  <h3 className="text-sm font-semibold">Title</h3>
  <p className="text-sm text-neutral-500">Move the cursor into the card and the glow follows along.</p>
</SpotlightCard>

Customize the glow color and radius:

<SpotlightCard spotlightColor="rgba(59,130,246,0.6)" radius={240}>
  <h3 className="text-sm font-semibold">Brand-colored glow</h3>
  <p className="text-sm text-neutral-500">Any valid CSS color value works.</p>
</SpotlightCard>

Props

PropTypeDefaultDescription
spotlightColorstringdark gray in light mode / white in dark modeGlow color; accepts any valid CSS color value
radiusnumber320Glow radius (px)
childrenReact.ReactNodeCard content
classNamestringAppended to the outermost container's className

Remaining props (such as onClick and id) are all forwarded to the outermost div.

How it works

  • Performance: mousemove never goes through React state. Coordinates are written straight into the CSS variables --wb-spot-x / --wb-spot-y with ref.style.setProperty and read back by a radial-gradient, so no matter how fast the cursor moves, no re-render is triggered
  • The border glow is implemented as a "1px padding container": the outer layer lays down a neutral base color as a static border, a cursor-following radial-gradient is stacked on top of it, and the inner card covers the middle so the gradient only shows through the 1px ring
  • The background bloom shares the same coordinate variables as the border glow, with the radius scaled up 1.75× and the opacity halved, producing a fainter, broader glow
  • Fading in and out runs on an opacity transition (the --wb-duration-fast token, 200ms by default): mouseenter sets --wb-spot-opacity to 1 and mouseleave sets it back to 0, so both glow layers fade together
  • Cards placed side by side stay independent: every variable is written on each card's own container, and no global state is shared
  • The default glow color is defined by class (dark gray in light mode, white in dark mode); passing spotlightColor overrides both through an inline style
  • The glow is kept even when the user has "reduce motion" enabled at the system level — it is a hover position cue that follows the cursor, not an animation that plays on its own, and only an opacity transition is involved; the DOM structure is identical before and after, so there is no SSR hydration difference
  • Touch devices have no hover, so the card presents its static border and its content and interactions are unaffected; every glow layer is aria-hidden and pointer-events-none, so it does not interfere with assistive technology or clicks

On this page