Shimmer Button

Primary button with a light sweep that loops across it.

Installation

  1. Install the dependencies

    $ npm i motion lucide-react
  2. Copy the source into components/ui/shimmer-button.tsx

    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>
      );
    }
    
  3. Use it

    The file exports the component and a Demo showing typical usage. Import whichever you need.