47 lines
1.6 KiB
JavaScript
47 lines
1.6 KiB
JavaScript
'use client';
|
|
|
|
import { motion } from 'framer-motion';
|
|
import { createPortal } from 'react-dom';
|
|
import { TrashIcon } from './Icons';
|
|
|
|
export default function ConfirmModal({ title, message, onConfirm, onCancel, confirmText = "确定删除" }) {
|
|
const content = (
|
|
<motion.div
|
|
className="modal-overlay"
|
|
role="dialog"
|
|
aria-modal="true"
|
|
onClick={(e) => {
|
|
e.stopPropagation();
|
|
onCancel();
|
|
}}
|
|
initial={{ opacity: 0 }}
|
|
animate={{ opacity: 1 }}
|
|
exit={{ opacity: 0 }}
|
|
style={{ zIndex: 10002 }}
|
|
>
|
|
<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 }}
|
|
className="glass card modal"
|
|
style={{ maxWidth: '400px' }}
|
|
onClick={(e) => e.stopPropagation()}
|
|
>
|
|
<div className="title" style={{ marginBottom: 12 }}>
|
|
<TrashIcon width="20" height="20" className="danger" />
|
|
<span>{title}</span>
|
|
</div>
|
|
<p className="muted" style={{ marginBottom: 24, fontSize: '14px', lineHeight: '1.6' }}>
|
|
{message}
|
|
</p>
|
|
<div className="row" style={{ gap: 12 }}>
|
|
<button className="button secondary" onClick={onCancel} style={{ flex: 1, background: 'rgba(255,255,255,0.05)', color: 'var(--text)' }}>取消</button>
|
|
<button className="button danger" onClick={onConfirm} style={{ flex: 1 }}>{confirmText}</button>
|
|
</div>
|
|
</motion.div>
|
|
</motion.div>
|
|
);
|
|
if (typeof document === 'undefined') return null;
|
|
return createPortal(content, document.body);
|
|
}
|