button-demo.tsx
button.tsx
prompt.md
Collapse
Reset
Copy Code
Download
Run
1
"use client";
2
3
import { useState, useEffect } from "react"
4
import { motion, AnimatePresence } from "framer-motion"
5
import { Check, Loader2 } from "lucide-react"
6
import { Button } from "./button"
7
8
export function ButtonDemo() {
9
const [state, setState] = useState<"idle" | "loading" | "success">("idle")
10
11
const handleClick = () => {
12
if (state === "idle") setState("loading")
13
else if (state === "loading") setState("success")
14
else if (state === "success") setState("idle")
15
}
16
17
return (
18
<div className="w-full h-full flex items-center justify-center p-8">
19
<Button
20
onClick={handleClick}
21
className="min-w-[125px] overflow-hidden"
22
>
23
<AnimatePresence mode="wait">
24
{state === "idle" && (
25
<motion.span key="idle" initial={{ opacity: 0, y: 15 }} animate={{ opacity: 1, y: 0 }} exit={{ opacity: 0, y: -15 }} transition={{ duration: 0.2 }}>
26
Label
27
</motion.span>
28
)}
29
{state === "loading" && (
30
<motion.span key="loading" initial={{ opacity: 0, y: 15 }} animate={{ opacity: 1, y: 0 }} exit={{ opacity: 0, y: -15 }} transition={{ duration: 0.2 }} className="flex items-center justify-center gap-2 text-zinc-400 dark:text-zinc-600">
31
<Loader2 className="w-3.5 h-3.5 animate-spin" />
32
<span>Saving...</span>
33
</motion.span>
34
)}
35
{state === "success" && (
36
<motion.span key="success" initial={{ opacity: 0, y: 15 }} animate={{ opacity: 1, y: 0 }} exit={{ opacity: 0, y: -15 }} transition={{ duration: 0.2 }} className="flex items-center justify-center gap-2">
37
<Check className="w-4 h-4" strokeWidth={2.5} />
38
<span>Success</span>
39
</motion.span>
40
)}
41
</AnimatePresence>
42
</Button>
43
</div>
44
)
45
}
46

