89 lines
3.1 KiB
TypeScript
89 lines
3.1 KiB
TypeScript
import { AnimatePresence, motion } from 'motion/react';
|
|
import {
|
|
Inbox,
|
|
MessageCircleHeart,
|
|
Settings2,
|
|
Sparkles,
|
|
} from 'lucide-react';
|
|
|
|
interface Props {
|
|
isAdmin: boolean;
|
|
menuOpen: boolean;
|
|
onCloseMenu: () => void;
|
|
onOpenFeedback: () => void;
|
|
onOpenHistory: () => void;
|
|
onToggleMenu: () => void;
|
|
}
|
|
|
|
export default function FeedbackLauncher({
|
|
isAdmin,
|
|
menuOpen,
|
|
onCloseMenu,
|
|
onOpenFeedback,
|
|
onOpenHistory,
|
|
onToggleMenu,
|
|
}: Props) {
|
|
return (
|
|
<div className="fixed bottom-20 right-4 md:bottom-6 md:right-6 z-[60]">
|
|
<motion.button
|
|
initial={{ scale: 0, opacity: 0 }}
|
|
animate={{ scale: 1, opacity: 1 }}
|
|
transition={{ delay: 0.4, type: 'spring', stiffness: 300, damping: 20 }}
|
|
whileHover={{ scale: 1.08 }}
|
|
whileTap={{ scale: 0.92 }}
|
|
onClick={onToggleMenu}
|
|
className="w-12 h-12 rounded-full bg-gradient-to-br from-blue-500 to-cyan-400 text-white shadow-lg shadow-blue-200 flex items-center justify-center group"
|
|
aria-label="反馈"
|
|
title="提建议 / 我的反馈"
|
|
>
|
|
<MessageCircleHeart size={20} className="drop-shadow group-hover:scale-110 transition-transform" />
|
|
<span className="absolute -top-0.5 -right-0.5 w-3 h-3 rounded-full bg-amber-300 ring-2 ring-white animate-pulse" />
|
|
</motion.button>
|
|
|
|
<AnimatePresence>
|
|
{menuOpen && (
|
|
<motion.div
|
|
initial={{ opacity: 0, scale: 0.9, y: 8 }}
|
|
animate={{ opacity: 1, scale: 1, y: 0 }}
|
|
exit={{ opacity: 0, scale: 0.9, y: 8 }}
|
|
transition={{ duration: 0.15 }}
|
|
className="absolute bottom-14 right-0 bg-white rounded-2xl shadow-xl border border-slate-100 p-1.5 min-w-[148px] flex flex-col gap-0.5"
|
|
>
|
|
<button
|
|
onClick={onOpenFeedback}
|
|
className="flex items-center gap-2 px-3 py-2 text-[12px] font-bold text-slate-700 rounded-lg hover:bg-blue-50 hover:text-blue-600 text-left"
|
|
>
|
|
<Sparkles size={14} className="text-blue-500" /> 提个建议
|
|
</button>
|
|
<button
|
|
onClick={onOpenHistory}
|
|
className="flex items-center gap-2 px-3 py-2 text-[12px] font-bold text-slate-700 rounded-lg hover:bg-emerald-50 hover:text-emerald-600 text-left"
|
|
>
|
|
<Inbox size={14} className="text-emerald-500" /> 我的反馈
|
|
</button>
|
|
{isAdmin && (
|
|
<>
|
|
<div className="h-px bg-slate-100 my-0.5" />
|
|
<a
|
|
href="#/admin/feedback"
|
|
onClick={onCloseMenu}
|
|
className="flex items-center gap-2 px-3 py-2 text-[12px] font-bold text-slate-700 rounded-lg hover:bg-violet-50 hover:text-violet-600"
|
|
>
|
|
<Settings2 size={14} className="text-violet-500" /> 反馈管理
|
|
</a>
|
|
</>
|
|
)}
|
|
</motion.div>
|
|
)}
|
|
</AnimatePresence>
|
|
|
|
{menuOpen && (
|
|
<div
|
|
className="fixed inset-0 z-[-1]"
|
|
onClick={onCloseMenu}
|
|
/>
|
|
)}
|
|
</div>
|
|
);
|
|
}
|