React + MotionBotones
Píldora de carga a check
Un botón píldora que muestra un spinner mientras trabaja y termina con un check que entra con muelle.
Ajustes
1200ms
Código
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 = "Reservar",
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" /> Listo
</motion.span>
)}
</AnimatePresence>
</motion.button>
);
}
Prompt para IA
Pégalo en ChatGPT, Claude o Cursor y adaptará el bloque a tu proyecto con estos ajustes, aunque no uses React.
Más en Botones
Dónde usarlo
Hay acciones que piden un «ya está» bien claro: reservar mesa, pagar un pedido o apuntarse a una clase del gimnasio. Esta píldora pasa por una espera corta y acaba con un check que entra rebotando, sin dejar dudas. Ese rebote final convierte un simple botón de carga en una animación de éxito que se nota.
Ajusta la duración a lo que tarda de verdad tu petición, normalmente menos de un segundo y medio. Si puede alargarse mucho más, añade al lado un texto como «Confirmando…» para que la espera no parezca atascada.