Smart suggestions
Hover the card — the glow follows your cursor with a soft radial falloff.
Instant feedback
Each card tracks its own pointer position via Framer Motion values.
Installation
npx shadcn@latest add https://tentui.com/r/glow-card.json
Usage
GlowCard is a styled <div> — drop any content inside.
import { GlowCard } from "@/components/glow-card";
export function PricingTier() {
return (
<GlowCard>
<div className="p-6">
<h3 className="text-lg font-semibold">Pro</h3>
<p className="text-sm text-muted-foreground">$29 / month</p>
</div>
</GlowCard>
);
}The glow is implemented as an absolutely-positioned layer between the outer ring and the inner content. The component subscribes to mousemove on the wrapper and feeds the cursor position into a radial-gradient via useMotionTemplate, so the gradient is recalculated on the GPU rather than re-rendering React on every move.
Patterns
Custom glow color
Pass any CSS color — RGB, HSL, OKLCH, or a CSS variable from your theme. Use a translucent color for a softer effect.
<GlowCard glowColor="hsl(142 71% 45% / 0.35)">…</GlowCard>
<GlowCard glowColor="oklch(0.7 0.2 140 / 0.4)">…</GlowCard>Disabling the glow
Disable per-instance when the card is non-interactive (read-only summary, disabled tier) so the affordance matches the behaviour.
<GlowCard disableGlow>{children}</GlowCard>Sizing the glow
Smaller glowSize for dense card grids, larger for hero cards. The default of 320 px feels right around a typical 320–480 px card width.
<GlowCard glowSize={180}>{compactContent}</GlowCard>
<GlowCard glowSize={500}>{heroContent}</GlowCard>Props
| Prop | Type | Default | Description |
|---|---|---|---|
glowColor | string | "hsl(217 91% 60%)" | Any CSS color string. Translucent colors give a softer, ambient glow. |
glowSize | number | 320 | Radius of the radial gradient in pixels. |
disableGlow | boolean | false | Skip rendering the glow layer entirely. |
className | string | — | Forwarded to the outer <div>. |
All other <div> props (onClick, id, style, …) pass through.
How the glow works
The outer wrapper has padding: 1px, the inner has the same border radius minus 1 px and a solid background — that gives you a precise hairline ring without a real border. The glow layer sits between them and is masked by the outer wrapper's overflow-hidden, so the gradient only ever shows along the ring.
useMotionValue and useMotionTemplate keep the gradient string in motion's reactive system. The component does not re-render React on mousemove — it just updates the CSS variable directly, which is why the effect stays smooth on long lists of cards.