NRVM

Back to Discover
MiscIntermediate

AirDrop Transfer UI

The classic AirDrop loading circle.

Live Preview
MacBook Pro AirDrop
"use client";
import { useState } from "react";
import { motion, AnimatePresence } from "framer-motion";
import { Wifi } from "lucide-react";

export function AirDropTransfer() {
  const [status, setStatus] = useState<"idle" | "sending" | "done">("idle");

  const handleSend = () => {
    if (status !== "idle") return;
    setStatus("sending");
    setTimeout(() => setStatus("done"), 2500);
    setTimeout(() => setStatus("idle"), 5000);
  };

  return (
    <div className="flex flex-col items-center justify-center w-full h-80 bg-[#0a0a0a] rounded-xl border border-border relative overflow-hidden">
      <div className="relative flex flex-col items-center">
        <button 
          onClick={handleSend}
          className="relative w-24 h-24 rounded-full bg-zinc-800 flex items-center justify-center cursor-pointer outline-none hover:bg-zinc-700 transition-colors z-10"
        >
          <img src="https://images.unsplash.com/photo-1534528741775-53994a69daeb?auto=format&fit=crop&w=128&q=80" alt="Avatar" className="w-full h-full object-cover rounded-full p-1" />
          
          <AnimatePresence>
            {status === "sending" && (
              <motion.svg 
                initial={{ opacity: 0 }}
                animate={{ opacity: 1 }}
                exit={{ opacity: 0 }}
                className="absolute inset-0 w-full h-full -rotate-90 pointer-events-none"
              >
                <motion.circle
                  cx="48"
                  cy="48"
                  r="46"
                  stroke="#3b82f6"
                  strokeWidth="4"
                  fill="none"
                  initial={{ strokeDasharray: "0 300" }}
                  animate={{ strokeDasharray: "300 300" }}
                  transition={{ duration: 2.5, ease: "linear" }}
                />
              </motion.svg>
            )}
          </AnimatePresence>
          
          <AnimatePresence>
            {status === "done" && (
              <motion.div 
                initial={{ scale: 0, opacity: 0 }}
                animate={{ scale: 1, opacity: 1 }}
                exit={{ scale: 0, opacity: 0 }}
                className="absolute inset-0 bg-blue-500 rounded-full flex items-center justify-center z-20"
              >
                <svg className="w-10 h-10 text-white" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={3}>
                  <path strokeLinecap="round" strokeLinejoin="round" d="M5 13l4 4L19 7" />
                </svg>
              </motion.div>
            )}
          </AnimatePresence>
        </button>
        <span className="mt-4 text-sm font-medium text-foreground">
          {status === "idle" ? "MacBook Pro" : status === "sending" ? "Sending..." : "Sent"}
        </span>
        {status === "idle" && (
          <span className="text-xs text-muted-foreground mt-1 flex items-center gap-1">
            <Wifi className="w-3 h-3" /> AirDrop
          </span>
        )}
      </div>
    </div>
  );
}