Shimmer Button
Primary button with a light sweep that loops across it.
components/ui/shimmer-button.tsx
"use client";
import { motion } from "motion/react";
import { ArrowRight } from "lucide-react";
import type { ButtonHTMLAttributes } from "react";
export function ShimmerButton({
children,
className = "",
...props
}: ButtonHTMLAttributes<HTMLButtonElement>) {
return (
<button
className={`group relative inline-flex items-center gap-2 overflow-hidden rounded-full bg-zinc-900 px-6 py-3 text-sm font-medium text-white shadow-[0_8px_24px_-8px_rgba(9,9,11,0.5)] ring-1 ring-zinc-900 transition-transform duration-200 hover:-translate-y-0.5 active:translate-y-0 ${className}`}
{...props}
>
<motion.span
aria-hidden
className="pointer-events-none absolute inset-y-0 left-0 w-1/2 bg-gradient-to-r from-transparent via-white/30 to-transparent"
initial={{ x: "-120%" }}
animate={{ x: "320%" }}
transition={{ duration: 2.2, repeat: Infinity, repeatDelay: 0.8, ease: "easeInOut" }}
/>
<span className="relative flex items-center gap-2">{children}</span>
</button>
);
}
export default function Demo() {
return (
<ShimmerButton>
Get started free
<ArrowRight className="size-4 transition-transform group-hover:translate-x-0.5" />
</ShimmerButton>
);
}
Installation
Install the dependencies
$ npm i motion lucide-reactCopy the source into
components/ui/shimmer-button.tsxcomponents/ui/shimmer-button.tsx"use client"; import { motion } from "motion/react"; import { ArrowRight } from "lucide-react"; import type { ButtonHTMLAttributes } from "react"; export function ShimmerButton({ children, className = "", ...props }: ButtonHTMLAttributes<HTMLButtonElement>) { return ( <button className={`group relative inline-flex items-center gap-2 overflow-hidden rounded-full bg-zinc-900 px-6 py-3 text-sm font-medium text-white shadow-[0_8px_24px_-8px_rgba(9,9,11,0.5)] ring-1 ring-zinc-900 transition-transform duration-200 hover:-translate-y-0.5 active:translate-y-0 ${className}`} {...props} > <motion.span aria-hidden className="pointer-events-none absolute inset-y-0 left-0 w-1/2 bg-gradient-to-r from-transparent via-white/30 to-transparent" initial={{ x: "-120%" }} animate={{ x: "320%" }} transition={{ duration: 2.2, repeat: Infinity, repeatDelay: 0.8, ease: "easeInOut" }} /> <span className="relative flex items-center gap-2">{children}</span> </button> ); } export default function Demo() { return ( <ShimmerButton> Get started free <ArrowRight className="size-4 transition-transform group-hover:translate-x-0.5" /> </ShimmerButton> ); }Use it
The file exports the component and a
Demoshowing typical usage. Import whichever you need.