Toast
Animated toast notification for copying an API key: click “Copy” to copy the key, triggers a smooth floating “Copied” toast, then fades out automatically inspired by dmytro.
Loading demo...
"use client";
import { cn, TRANSITION } from "@/lib/utils";
import { AlertCircleIcon } from "@hugeicons/core-free-icons";
import { HugeiconsIcon } from "@hugeicons/react";
import { AnimatePresence, motion, MotionConfig } from "motion/react";
import { useRef, useState } from "react";
import { buttonVariants } from "@/components/ui/button";
const variant = {
show: {
opacity: 1,
y: -85,
filter: "blur(0px)",
},
hidden: {
y: -40,
opacity: 0,
filter: "blur(4px)",
},
};
const BetterToast = () => {
const key = "sk_live_••••••••••••••••••";
const timeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);
const [isActive, setIsActive] = useState(false);
const handleCopy = async () => {
await navigator.clipboard.writeText(key);
setIsActive(true);
if (timeoutRef.current) clearTimeout(timeoutRef.current);
timeoutRef.current = setTimeout(() => {
setIsActive(false);
}, 1600);
};
return (
<MotionConfig transition={TRANSITION}>
<div className="size-full flex items-center justify-center bg-background">
<div className="max-w-lg w-full mx-auto p-1 rounded-xl border border-border/25 bg-muted">
<div className="max-w-lg w-full mx-auto border border-border bg-background rounded-lg p-4 flex flex-col gap-4">
<div>
<h1 className="font-semibold text-xl">API Key</h1>
<p className="text-muted-foreground">Start building today</p>
</div>
<div className="flex flex-col items-end gap-2">
<div className="w-full relative z-0">
<div className="border p-2 rounded-xl flex items-center justify-between z-20 bg-background">
<span>{key}</span>
<button
onClick={handleCopy}
className={cn(
buttonVariants({ variant: "outline" }),
"bg-muted opacity-100 transition duration-300",
{
"opacity-0": isActive,
},
)}
>
Copy
</button>
</div>
<AnimatePresence>
{isActive && (
<motion.div
variants={variant}
initial="hidden"
animate="show"
exit="hidden"
className="border border-blue-500 w-fit rounded bg-blue-50 text-blue-500 px-2 py-0.5 font-medium absolute right-2 text-sm -z-10"
>
Copied
</motion.div>
)}
</AnimatePresence>
</div>
<p className="text-muted-foreground flex items-center gap-2 w-fit text-sm">
<HugeiconsIcon icon={AlertCircleIcon} className="size-4" />
<span>Need another API Key?</span>
</p>
</div>
</div>
</div>
</div>
</MotionConfig>
);
};
export default BetterToast;