"use client";
import { useState } from "react";
import { motion, AnimatePresence } from "framer-motion";
import { Icon } from "@iconify/react";
interface CircleMenuItem {
icon: string;
label: string;
href?: string;
}
interface CircleMenuProps {
items: CircleMenuItem[];
/** Radius in px of the circle. Default: 90 */
radius?: number;
}
export function CircleMenu({ items, radius = 90 }: CircleMenuProps) {
const [open, setOpen] = useState(false);
const angleStep = (2 * Math.PI) / items.length;
return (
<div className="relative flex items-center justify-center" style={{ width: radius * 2 + 80, height: radius * 2 + 80 }}>
{/* Items */}
{items.map((item, i) => {
const angle = angleStep * i - Math.PI / 2;
const x = Math.cos(angle) * radius;
const y = Math.sin(angle) * radius;
return (
<AnimatePresence key={item.label}>
{open && (
<motion.a
href={item.href ?? "#"}
initial={{ opacity: 0, x: 0, y: 0, scale: 0.3 }}
animate={{ opacity: 1, x, y, scale: 1 }}
exit={{ opacity: 0, x: 0, y: 0, scale: 0.3 }}
transition={{ type: "spring", stiffness: 400, damping: 28, delay: i * 0.04 }}
className="absolute flex flex-col items-center gap-1 group"
style={{ transform: `translate(${x}px, ${y}px)` }}
>
<div className="w-11 h-11 rounded-full bg-zinc-900 border border-white/20 flex items-center justify-center text-white hover:bg-indigo-500 hover:border-indigo-400 transition-all duration-200 shadow-xl">
<Icon icon={item.icon} fontSize={20} />
</div>
<span className="text-[10px] text-zinc-400 group-hover:text-white transition-colors whitespace-nowrap bg-zinc-900/80 px-1.5 py-0.5 rounded backdrop-blur">
{item.label}
</span>
</motion.a>
)}
</AnimatePresence>
);
})}
{/* Center toggle button */}
<motion.button
onClick={() => setOpen(!open)}
animate={{ rotate: open ? 45 : 0, backgroundColor: open ? "rgba(99,102,241,0.3)" : "rgba(24,24,27,0.9)" }}
className="w-14 h-14 rounded-full border border-white/20 flex items-center justify-center text-white shadow-2xl z-10 relative"
aria-label={open ? "Close menu" : "Open menu"}
>
<motion.span animate={{ rotate: open ? 45 : 0 }} transition={{ type: "spring", stiffness: 500, damping: 30 }}>
<Icon icon="solar:add-linear" fontSize={22} />
</motion.span>
</motion.button>
{/* Orbit ring (decorative) */}
<div
className="absolute rounded-full border border-dashed border-white/10 pointer-events-none"
style={{ width: radius * 2, height: radius * 2 }}
/>
</div>
);
}