ComponentsAnimated Button

Animated Button

A highly customisable animated button with shimmer, glow, pulse, and ripple effects β€” built with pure CSS, zero dependencies.

shimmerglowpulseripple

Installation

Use the CLI for the fastest setup, or copy the file manually.

Run this command in your project root. The CLI will create components/ui/ and write the file automatically.

Terminal

$ npx @nehal712521/inprogress add button

βœ” Fetching from registry…

βœ” Created components/ui/AnimatedButton.tsx

βœ” Done!

pnpmpnpm dlx @nehal712521/inprogress add button
npmnpx @nehal712521/inprogress add button
bunbunx @nehal712521/inprogress add button

See all available components β†’ npx @nehal712521/inprogress list

Usage

Import the component and pick a variant.

Variants

Four animation styles, each a pure CSS effect.

Shimmer

A light-streak sweeps across the button on a loop β€” great for primary CTAs.

<AnimatedButton variant="shimmer">Get Started</AnimatedButton>

Glow

A soft ambient glow pulses around the border. Hover reveals an intense halo.

<AnimatedButton variant="glow">Learn More</AnimatedButton>

Pulse

A ring expands outward from the button in a heartbeat rhythm β€” draws the eye.

<AnimatedButton variant="pulse">Subscribe</AnimatedButton>

Ripple

Click anywhere on the button to spawn a ripple wave from your cursor position.

<AnimatedButton variant="ripple">Click Me</AnimatedButton>

Sizes

tsx
<AnimatedButton size="sm">Small</AnimatedButton>
<AnimatedButton size="md">Medium</AnimatedButton>
<AnimatedButton size="lg">Large</AnimatedButton>

Disabled State

tsx
<AnimatedButton variant="shimmer" disabled>Disabled</AnimatedButton>

Component Source

Copy this into components/ui/AnimatedButton.tsx

tsx
"use client";
import React, { useRef } from "react";

type Variant = "shimmer" | "glow" | "pulse" | "ripple";
type Size    = "sm" | "md" | "lg";

interface AnimatedButtonProps {
  children: React.ReactNode;
  variant?: Variant;
  size?: Size;
  disabled?: boolean;
  onClick?: (e: React.MouseEvent<HTMLButtonElement>) => void;
  className?: string;
  type?: "button" | "submit" | "reset";
  fullWidth?: boolean;
}

const sizeMap: Record<Size, string> = {
  sm: "px-4 py-1.5 text-sm",
  md: "px-6 py-2.5 text-sm",
  lg: "px-8 py-3.5 text-base",
};

export default function AnimatedButton({
  children,
  variant = "shimmer",
  size = "md",
  disabled = false,
  onClick,
  className = "",
  type = "button",
  fullWidth = false,
}: AnimatedButtonProps) {
  const btnRef = useRef<HTMLButtonElement>(null);
  const rippleRef = useRef<HTMLSpanElement>(null);

  const handleClick = (e: React.MouseEvent<HTMLButtonElement>) => {
    if (variant === "ripple" && btnRef.current && rippleRef.current) {
      const btn = btnRef.current;
      const ripple = rippleRef.current;
      const rect = btn.getBoundingClientRect();
      const size = Math.max(rect.width, rect.height) * 2;
      ripple.style.width  = `${size}px`;
      ripple.style.height = `${size}px`;
      ripple.style.left   = `${e.clientX - rect.left - size / 2}px`;
      ripple.style.top    = `${e.clientY - rect.top  - size / 2}px`;
      ripple.classList.remove("animate-ripple");
      void ripple.offsetWidth;
      ripple.classList.add("animate-ripple");
    }
    onClick?.(e);
  };

  return (
    <>
      <style>{`/* ... paste the CSS from the source file ... `}</style>
      <button
        ref={btnRef}
        type={type}
        disabled={disabled}
        onClick={handleClick}
        className={`animated-btn ${sizeMap[size]} btn-${variant} ${fullWidth ? "w-full" : ""} ${className}`}
      >
        {variant === "ripple" && <span ref={rippleRef} className="ripple-dot" />}
        <span className="relative z-10 flex items-center gap-2">{children}</span>
      </button>
    </>
  );
}

API Reference

All props accepted by AnimatedButton.

PropTypeDefaultDescription
variant"shimmer" | "glow" | "pulse" | "ripple""shimmer"Controls the animation style.
size"sm" | "md" | "lg""md"Controls padding and font size.
disabledbooleanfalseDisables the button and fades it out.
fullWidthbooleanfalseMakes the button stretch to full container width.
onClick(e: MouseEvent) => voidβ€”Click handler forwarded to the native button.
classNamestring""Extra Tailwind / CSS classes merged in.
type"button" | "submit" | "reset""button"Native button type attribute.