Glow Border Card
A beam of light travels endlessly around the card border.
Most popular
Team plan
Everything a growing team needs.
$24/seat
- Unlimited projects
- Advanced analytics
- Priority support
components/ui/glow-card.tsx
"use client";
import { motion } from "motion/react";
import { Check } from "lucide-react";
import type { ReactNode } from "react";
type GlowCardProps = {
children: ReactNode;
className?: string;
/** Seconds for one full rotation of the border light */
speed?: number;
};
export function GlowCard({ children, className = "", speed = 4 }: GlowCardProps) {
return (
<div className={`relative overflow-hidden rounded-2xl p-px ${className}`}>
<motion.div
aria-hidden
className="absolute left-1/2 top-1/2 aspect-square w-[250%] bg-[conic-gradient(from_0deg,transparent_0deg,transparent_270deg,#60a5fa_320deg,#a78bfa_360deg)]"
style={{ x: "-50%", y: "-50%" }}
animate={{ rotate: 360 }}
transition={{ duration: speed, repeat: Infinity, ease: "linear" }}
/>
<div aria-hidden className="absolute inset-0 rounded-2xl ring-1 ring-inset ring-zinc-200" />
<div className="relative h-full rounded-[15px] bg-white">{children}</div>
</div>
);
}
export default function Demo() {
return (
<GlowCard className="w-80">
<div className="p-7">
<span className="rounded-full bg-blue-50 px-2.5 py-1 text-xs font-medium text-blue-700">Most popular</span>
<h3 className="mt-4 text-lg font-semibold text-zinc-900">Team plan</h3>
<p className="mt-1 text-sm text-zinc-500">Everything a growing team needs.</p>
<p className="mt-5 text-4xl font-semibold tracking-tight text-zinc-900">
$24<span className="text-base font-normal text-zinc-500">/seat</span>
</p>
<ul className="mt-5 space-y-2.5 text-sm text-zinc-600">
{["Unlimited projects", "Advanced analytics", "Priority support"].map((f) => (
<li key={f} className="flex items-center gap-2">
<Check className="size-4 text-blue-600" /> {f}
</li>
))}
</ul>
</div>
</GlowCard>
);
}
Installation
Install the dependencies
$ npm i motion lucide-reactCopy the source into
components/ui/glow-card.tsxcomponents/ui/glow-card.tsx"use client"; import { motion } from "motion/react"; import { Check } from "lucide-react"; import type { ReactNode } from "react"; type GlowCardProps = { children: ReactNode; className?: string; /** Seconds for one full rotation of the border light */ speed?: number; }; export function GlowCard({ children, className = "", speed = 4 }: GlowCardProps) { return ( <div className={`relative overflow-hidden rounded-2xl p-px ${className}`}> <motion.div aria-hidden className="absolute left-1/2 top-1/2 aspect-square w-[250%] bg-[conic-gradient(from_0deg,transparent_0deg,transparent_270deg,#60a5fa_320deg,#a78bfa_360deg)]" style={{ x: "-50%", y: "-50%" }} animate={{ rotate: 360 }} transition={{ duration: speed, repeat: Infinity, ease: "linear" }} /> <div aria-hidden className="absolute inset-0 rounded-2xl ring-1 ring-inset ring-zinc-200" /> <div className="relative h-full rounded-[15px] bg-white">{children}</div> </div> ); } export default function Demo() { return ( <GlowCard className="w-80"> <div className="p-7"> <span className="rounded-full bg-blue-50 px-2.5 py-1 text-xs font-medium text-blue-700">Most popular</span> <h3 className="mt-4 text-lg font-semibold text-zinc-900">Team plan</h3> <p className="mt-1 text-sm text-zinc-500">Everything a growing team needs.</p> <p className="mt-5 text-4xl font-semibold tracking-tight text-zinc-900"> $24<span className="text-base font-normal text-zinc-500">/seat</span> </p> <ul className="mt-5 space-y-2.5 text-sm text-zinc-600"> {["Unlimited projects", "Advanced analytics", "Priority support"].map((f) => ( <li key={f} className="flex items-center gap-2"> <Check className="size-4 text-blue-600" /> {f} </li> ))} </ul> </div> </GlowCard> ); }Use it
The file exports the component and a
Demoshowing typical usage. Import whichever you need.