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.
npx shadcn@latest add https://webberui.com/r/spotlight-card.jsonPlayground
Tune the props live — the code snippet updates as you go, so you can dial in the look you want before copying it.
<SpotlightCard />
Installation
npx shadcn@latest add https://webberui.com/r/spotlight-card.jsonOr, 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
| Prop | Type | Default | Description |
|---|---|---|---|
spotlightColor | string | dark gray in light mode / white in dark mode | Glow color; accepts any valid CSS color value |
radius | number | 320 | Glow radius (px) |
children | React.ReactNode | — | Card content |
className | string | — | Appended 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-ywithref.style.setPropertyand read back by aradial-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-fasttoken, 200ms by default):mouseentersets--wb-spot-opacityto 1 andmouseleavesets 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
spotlightColoroverrides 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-hiddenandpointer-events-none, so it does not interfere with assistive technology or clicks
Card Deck
A draggable stacked card deck — flick a card out in any of four directions, the next one fills in automatically, with infinite loop or draw-until-empty modes.
Infinite Drag Canvas
An infinitely pannable portfolio canvas that scatters cards across a boundless space, with drag (including momentum), keyboard panning, and one-click recentering.