React + MotionBoutons

Pilule chargement vers coche

Un bouton pilule qui affiche un spinner pendant l’action, puis une coche qui arrive avec un effet ressort.

Réglages

1200ms

Code

import { useState } from "react";
import { AnimatePresence, motion } from "framer-motion";
import { Check, Loader2 } from "lucide-react";

const spring = { type: "spring", stiffness: 300, damping: 30 } as const;

interface LoadingCheckButtonProps {
  text?: string;
  color?: string;
  /** Duración de la carga simulada en ms. */
  delay?: number;
}

export default function LoadingCheckButton({
  text = "Réserver",
  color = "#0071e3",
  delay = 1200,
}: LoadingCheckButtonProps) {
  const [state, setState] = useState<"idle" | "load" | "done">("idle");

  const go = () => {
    if (state !== "idle") return;
    setState("load");
    setTimeout(() => setState("done"), delay);
    setTimeout(() => setState("idle"), delay + 1600);
  };

  return (
    <motion.button
      type="button"
      whileTap={{ scale: 0.96 }}
      onClick={go}
      className="flex min-w-36 items-center justify-center gap-2 rounded-full px-6 py-3 text-sm font-medium text-white shadow-[0_1px_2px_rgba(0,0,0,0.03),0_8px_28px_rgba(0,0,0,0.05)]"
      style={{ backgroundColor: color }}
    >
      <AnimatePresence mode="wait" initial={false}>
        {state === "idle" ? (
          <motion.span
            key="idle"
            initial={{ opacity: 0 }}
            animate={{ opacity: 1 }}
            exit={{ opacity: 0 }}
          >
            {text}
          </motion.span>
        ) : state === "load" ? (
          <motion.span key="load" initial={{ scale: 0.6 }} animate={{ scale: 1 }}>
            <Loader2 className="h-4 w-4 animate-spin" />
          </motion.span>
        ) : (
          <motion.span
            key="done"
            initial={{ scale: 0.4, opacity: 0 }}
            animate={{ scale: 1, opacity: 1 }}
            transition={spring}
            className="flex items-center gap-2"
          >
            <Check className="h-4 w-4" /> Terminé
          </motion.span>
        )}
      </AnimatePresence>
    </motion.button>
  );
}

Prompt pour l’IA

Collez-le dans ChatGPT, Claude ou Cursor : le bloc sera adapté à votre projet avec ces réglages, même sans React.

Plus dans Boutons

Où l’utiliser

Certaines actions méritent un « c’est fait » bien net : réserver une table, payer une commande, s’inscrire à un cours de sport. Cette pilule passe par une courte attente et se termine par une coche qui rebondit, pour que personne ne se demande si ça a marché. Ce dernier rebond transforme un simple bouton de chargement en animation de succès qu’on remarque.

Réglez la durée sur le temps réel de votre requête, en général moins d’une seconde et demie. Si cela peut prendre bien plus longtemps, ajoutez à côté un texte comme « Confirmation… » pour que l’attente ne paraisse pas bloquée.