NEW
shadcn registry is live·
shadcn registry is live·
shadcn registry is live·
shadcn registry is live·
shadcn registry is live·
shadcn registry is live·
shadcn registry is live·
shadcn registry is live·
shadcn registry is live·
shadcn registry is live·
shadcn registry is live·
shadcn registry is live·
Learn more
Skip to content
Docs

Status Button

A button that transitions the status change. Click to see the animation.

requires interactionclick
Loading...

Installation

CLI

pnpm dlx shadcn@latest add https://animata.design/r/button/status-button.json

Manual

Install dependencies

npm install motion lucide-react

Run the following command

It will create a new file status-button.tsx inside the components/animata/button directory.

mkdir -p components/animata/button && touch components/animata/button/status-button.tsx

Paste the code

Open the newly created file and paste the following code:

import { CheckCircle2, CircleDashed } from "lucide-react";
import { AnimatePresence, motion } from "motion/react";
import { useState } from "react";
 
import { cn } from "@/lib/utils";
 
const wait = async (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));
 
export default function StatusButton() {
  const [status, setStatus] = useState<"loading" | "Add to cart" | "Added to cart">();
  const isEnabled = !status || status === "Add to cart";
 
  const changeStatus = async () => {
    if (!isEnabled) {
      return;
    }
 
    setStatus("loading");
    await wait(1500);
    setStatus("Added to cart");
    await wait(1500);
    setStatus("Add to cart");
  };
 
  return (
    <button
      onClick={changeStatus}
      disabled={!isEnabled}
      className="group/status relative h-10 min-w-40 overflow-hidden rounded-md bg-teal-500 px-6 text-sm font-semibold text-white transition-colors duration-300 hover:bg-teal-600"
    >
      <AnimatePresence mode="wait" initial={false}>
        <motion.span
          // Remount the component so that the animation can be restarted
          key={status}
          initial={{ opacity: 0, y: -15 }}
          animate={{ opacity: 1, y: 0 }}
          exit={{ opacity: 0, y: 15 }}
          transition={{ duration: 0.075 }}
          className={cn("flex items-center justify-center gap-1")}
        >
          {status === "Added to cart" && (
            <motion.span
              className="h-fit w-fit"
              initial={{ scale: 0 }}
              animate={{ scale: 1 }}
              transition={{ delay: 0.075, type: "spring" }}
            >
              <CheckCircle2 className="h-4 w-4 fill-white stroke-teal-500 group-hover/status:stroke-teal-600" />
            </motion.span>
          )}
 
          {status === "loading" ? (
            <CircleDashed className="h-4 w-4 animate-spin" />
          ) : (
            (status ?? "Add to cart")
          )}
        </motion.span>
      </AnimatePresence>
    </button>
  );
}

Credits

Built by hari

Inspired by https://animations.dev/gallery