前端重构实现
This commit is contained in:
@@ -0,0 +1,87 @@
|
||||
import * as Dialog from '@radix-ui/react-dialog';
|
||||
import { X } from 'lucide-react';
|
||||
import { motion, AnimatePresence } from 'framer-motion';
|
||||
|
||||
/**
|
||||
* Modal 组件
|
||||
* 使用 Radix UI Dialog 实现的模态弹窗
|
||||
* @param {Object} props
|
||||
* @param {boolean} props.isOpen - 是否打开
|
||||
* @param {Function} props.onClose - 关闭回调
|
||||
* @param {React.ReactNode} props.children - 子元素
|
||||
* @param {'sm'|'md'|'lg'} props.maxWidth - 最大宽度
|
||||
* @param {string} props.title - 标题(可选)
|
||||
*/
|
||||
const Modal = ({
|
||||
isOpen,
|
||||
onClose,
|
||||
children,
|
||||
maxWidth = 'md',
|
||||
title
|
||||
}) => {
|
||||
// 最大宽度映射
|
||||
const maxWidthMap = {
|
||||
sm: 'max-w-sm',
|
||||
md: 'max-w-lg',
|
||||
lg: 'max-w-2xl'
|
||||
};
|
||||
|
||||
return (
|
||||
<Dialog.Root open={isOpen} onOpenChange={(open) => !open && onClose()}>
|
||||
<AnimatePresence>
|
||||
{isOpen && (
|
||||
<Dialog.Portal forceMount>
|
||||
{/* 遮罩层 */}
|
||||
<Dialog.Overlay asChild>
|
||||
<motion.div
|
||||
initial={{ opacity: 0 }}
|
||||
animate={{ opacity: 1 }}
|
||||
exit={{ opacity: 0 }}
|
||||
className="fixed inset-0 bg-black/60 backdrop-blur-xl z-[100]"
|
||||
/>
|
||||
</Dialog.Overlay>
|
||||
|
||||
{/* 内容区 */}
|
||||
<Dialog.Content asChild>
|
||||
<motion.div
|
||||
initial={{ opacity: 0, scale: 0.95, y: 20 }}
|
||||
animate={{ opacity: 1, scale: 1, y: 0 }}
|
||||
exit={{ opacity: 0, scale: 0.95, y: 20 }}
|
||||
transition={{ duration: 0.3, ease: [0.16, 1, 0.3, 1] }}
|
||||
className={`
|
||||
fixed top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2
|
||||
glass-card ${maxWidthMap[maxWidth]} w-[calc(100%-2rem)] p-8
|
||||
border border-white/10 shadow-2xl z-[101]
|
||||
`}
|
||||
>
|
||||
{/* 关闭按钮 */}
|
||||
<Dialog.Close asChild>
|
||||
<button
|
||||
className="absolute top-6 right-6 text-white/40 hover:text-white transition-colors"
|
||||
aria-label="关闭"
|
||||
>
|
||||
<X className="w-5 h-5" />
|
||||
</button>
|
||||
</Dialog.Close>
|
||||
|
||||
{/* 标题 */}
|
||||
{title && (
|
||||
<Dialog.Title className="text-2xl font-serif mb-6">
|
||||
{title}
|
||||
</Dialog.Title>
|
||||
)}
|
||||
|
||||
{/* 内容 */}
|
||||
<div className="max-h-[70vh] overflow-y-auto pr-2 custom-scrollbar">
|
||||
{children}
|
||||
</div>
|
||||
</motion.div>
|
||||
</Dialog.Content>
|
||||
</Dialog.Portal>
|
||||
)}
|
||||
</AnimatePresence>
|
||||
</Dialog.Root>
|
||||
);
|
||||
};
|
||||
|
||||
export default Modal;
|
||||
Reference in New Issue
Block a user