# Button Shimmer Sweep — Animated React Button

> A slanted band of light crosses the button on a slow loop and fires again, faster, the moment you hover.

- Category: [Buttons](https://pixelpapa.com/components/buttons.md)
- Tags: button, shimmer, shine, loop, hover
- Dependencies: lucide-react (plus React and Tailwind CSS v4)
- Last updated: 2026-11-13
- Live preview: https://pixelpapa.com/components/buttons/button-shimmer-sweep

## Install

```bash
npx shadcn@latest add "https://pixelpapa.com/r/button-shimmer-sweep.json"
```

The file is written to `components/pixelpapa/button-shimmer-sweep.tsx`. To install manually, run `npm install lucide-react` and copy the source below into your project. It imports `cn` from `@/lib/utils`, which every shadcn project has.

## Source

```tsx
"use client";

import { ArrowRight, Sparkles } from "lucide-react";
import type { ComponentProps, CSSProperties } from "react";
import { cn } from "@/lib/utils";

type ShimmerButtonProps = ComponentProps<"button"> & {
  /** Seconds between idle sweeps. */
  interval?: number;
  /** Any CSS colour for the light band. */
  shine?: string;
};

export function ShimmerButton({
  interval = 3.2,
  shine = "color-mix(in oklch, white 42%, transparent)",
  className,
  children,
  ...props
}: ShimmerButtonProps) {
  const band =
    "pointer-events-none absolute inset-y-0 left-0 w-2/5 [background:linear-gradient(90deg,transparent,var(--pp-shine),transparent)]";

  return (
    <button
      style={{ "--pp-shine": shine } as CSSProperties}
      className={cn(
        "group relative inline-flex h-11 items-center justify-center gap-2 overflow-hidden rounded-full bg-primary px-6 text-sm font-medium text-primary-foreground shadow-[inset_0_1px_0_rgb(255_255_255/0.22),0_8px_20px_-8px_var(--primary)] transition-transform duration-200 hover:-translate-y-0.5 active:translate-y-0 active:scale-[0.98]",
        className,
      )}
      {...props}
    >
      <style>{`
        @keyframes pp-button-shimmer-sweep-move {
          0% { transform: translateX(-130%) skewX(-22deg); }
          42%, 100% { transform: translateX(330%) skewX(-22deg); }
        }
      `}</style>
      {/* Idle loop: travels for 42% of the cycle, rests for the remainder. */}
      <span
        aria-hidden
        className={cn(band, "motion-reduce:hidden")}
        style={{ animation: `pp-button-shimmer-sweep-move ${interval}s cubic-bezier(0.4, 0, 0.2, 1) infinite` }}
      />
      {/* Hover sweep: zero duration on the way back so it never plays in reverse. */}
      <span
        aria-hidden
        className={cn(
          band,
          "-translate-x-[130%] -skew-x-[22deg] transition-transform duration-0 group-hover:translate-x-[330%] group-hover:duration-700 group-hover:ease-out",
        )}
      />
      <span className="relative inline-flex items-center gap-2">{children}</span>
    </button>
  );
}

export default function ButtonShimmerSweepDemo() {
  return (
    <div className="flex flex-wrap items-center justify-center gap-4">
      <ShimmerButton>
        <Sparkles className="size-4" />
        Upgrade to Pro
      </ShimmerButton>
      <ShimmerButton
        interval={4}
        shine="color-mix(in oklch, var(--primary) 55%, transparent)"
        className="bg-foreground text-background shadow-none"
      >
        Start free trial
        <ArrowRight className="size-4 transition-transform duration-300 group-hover:translate-x-0.5" />
      </ShimmerButton>
      <ShimmerButton
        interval={5}
        shine="color-mix(in oklch, var(--primary) 22%, transparent)"
        className="border border-border bg-card text-foreground shadow-none"
      >
        View changelog
      </ShimmerButton>
    </div>
  );
}
```

## AI prompt

```text
Add the "Button Shimmer Sweep" component from PixelPapa UI to this project.

What it is: A slanted band of light crosses the button on a slow loop and fires again, faster, the moment you hover.
Category: Buttons. Depends on: lucide-react.

1. Install it with the shadcn CLI:
   npx shadcn@latest add "https://pixelpapa.com/r/button-shimmer-sweep.json"
   (If the CLI is unavailable, fetch that URL, write files[0].content to components/pixelpapa/button-shimmer-sweep.tsx and install the listed dependencies.)
2. Import it from "@/components/pixelpapa/button-shimmer-sweep" and place it where I describe below.
3. Keep its animation timings and accessibility attributes. Replace the demo copy and data with content that fits my product, and use my existing theme tokens (bg-background, text-foreground, bg-primary, border-border) rather than hard-coded colours.

Where to use it: <describe the page and position here>
```

## More buttons

- [Button 3D Press](https://pixelpapa.com/components/buttons/button-3d-press.md): A raised key with a real edge and cast shadow: it lifts slightly on hover, sinks hard on press and bounces back on release.
- [Button Async States](https://pixelpapa.com/components/buttons/button-async-states.md) (Pro): Runs a promise and morphs through idle, a collapsed spinner, then a success or error label, animating its width between each.
- [Button Border Beam](https://pixelpapa.com/components/buttons/button-border-beam.md) (Pro): A comet of light laps the button's border on a loop, with a soft halo that follows the head of the beam.
- [Button Confetti Burst](https://pixelpapa.com/components/buttons/button-confetti-burst.md) (Pro): Throws a fan of DOM confetti from the exact point you clicked; pieces arc up, tumble and fall under gravity. No canvas.
- [Button Copy Feedback](https://pixelpapa.com/components/buttons/button-copy-feedback.md) (Pro): Copies a value to the clipboard, then swaps its icon for a drawn check and rolls the label to "Copied" before settling back.
- [Button Gradient Border Glow](https://pixelpapa.com/components/buttons/button-gradient-border-glow.md) (Pro): A flowing gradient outline with a blurred twin underneath; the glow brightens on hover and leans toward the cursor.
