video-flow-b/components/ui/FloatingGlassPanel.tsx
2025-07-29 21:22:51 +08:00

61 lines
1.6 KiB
TypeScript

'use client';
import { motion, AnimatePresence } from 'framer-motion';
import { ReactNode } from 'react';
type FloatingGlassPanelProps = {
open: boolean;
onClose?: () => void;
children: ReactNode;
width?: string;
r_key?: string | number;
};
export default function FloatingGlassPanel({ open, onClose, children, width = '320px', r_key }: FloatingGlassPanelProps) {
// 定义弹出动画
const bounceAnimation = {
scale: [0.95, 1.02, 0.98, 1],
rotate: [0, -1, 1, -1, 0],
};
return (
<AnimatePresence>
{open && (
<motion.div
key={r_key}
className="fixed top-1/2 left-1/2 z-50 cursor-grab active:cursor-grabbing"
style={{ transform: 'translate(-50%, -50%)', pointerEvents: 'auto' }}
drag
dragElastic={0.2}
dragMomentum={false}
initial={{ opacity: 0, scale: 0.95, rotate: 0 }}
animate={{
opacity: 1,
...bounceAnimation,
}}
exit={{ opacity: 0, scale: 0.95, rotate: 0 }}
transition={{
duration: 0.6,
ease: [0.19, 1, 0.22, 1],
scale: {
duration: 0.4,
times: [0, 0.3, 0.6, 1]
},
rotate: {
duration: 0.4,
times: [0, 0.2, 0.4, 0.6, 1]
}
}}
>
<div
style={{ width }}
className="rounded-xl backdrop-blur-md bg-white/10 border border-white/20 shadow-xl text-white p-4"
>
{children}
</div>
</motion.div>
)}
</AnimatePresence>
);
}