maplestory/frontend/src/components/ConfirmDialog.jsx
caadiq b63ab39977 ConfirmDialog 테마 토큰화 + 입력 필드 테마 전환 플래시 수정
- ConfirmDialog 전체를 dialog/icon/ring/danger-btn 토큰으로 이관
- 캐릭터 닉네임 입력의 transition 제거로 테마 전환 시 검은색 플래시 해결

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-18 12:20:55 +09:00

132 lines
5.6 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { motion, AnimatePresence } from 'framer-motion'
export default function ConfirmDialog({
open,
onClose,
onConfirm,
title,
description,
confirmText = '확인',
cancelText = '취소',
destructive = false,
loading = false,
}) {
const accent = destructive
? {
ringColor: 'var(--ring-danger)',
iconColor: 'var(--danger-text)',
iconBg: 'var(--icon-danger-bg)',
iconBorder: 'var(--icon-danger-border)',
}
: {
ringColor: 'var(--ring-info)',
iconColor: 'var(--accent-bright)',
iconBg: 'var(--icon-info-bg)',
iconBorder: 'var(--icon-info-border)',
}
return (
<AnimatePresence>
{open && (
<motion.div
key="backdrop"
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
transition={{ duration: 0.18 }}
className="fixed inset-0 z-50 flex items-center justify-center p-4 backdrop-blur-md"
style={{ background: 'var(--dialog-backdrop)' }}
onClick={onClose}
>
<motion.div
key="dialog"
initial={{ opacity: 0, scale: 0.94, y: 8 }}
animate={{ opacity: 1, scale: 1, y: 0 }}
exit={{ opacity: 0, scale: 0.96, y: 4 }}
transition={{ duration: 0.2, ease: [0.22, 1, 0.36, 1] }}
className="w-full max-w-md rounded-2xl border shadow-2xl ring-1"
style={{
backgroundImage: 'linear-gradient(to bottom, var(--dialog-bg-from), var(--dialog-bg-to))',
borderColor: 'var(--dialog-border)',
'--tw-ring-color': accent.ringColor,
}}
onClick={(e) => e.stopPropagation()}
>
<div className="px-7 pt-7 pb-3 flex items-start gap-4">
<div
className="shrink-0 w-11 h-11 rounded-xl border flex items-center justify-center"
style={{ background: accent.iconBg, borderColor: accent.iconBorder, color: accent.iconColor }}
>
{destructive ? (
<svg width="22" height="22" viewBox="0 0 24 24" fill="none">
<path d="M12 9V13M12 17H12.01M10.29 3.86L1.82 18C1.64 18.31 1.55 18.67 1.55 19.03C1.55 19.4 1.65 19.76 1.83 20.07C2 20.39 2.26 20.65 2.57 20.83C2.88 21.01 3.24 21.1 3.6 21.1H20.47C20.83 21.1 21.19 21.01 21.5 20.83C21.81 20.65 22.07 20.39 22.24 20.07C22.42 19.76 22.52 19.4 22.52 19.03C22.52 18.67 22.43 18.31 22.25 18L13.78 3.86C13.6 3.56 13.35 3.31 13.04 3.14C12.74 2.96 12.4 2.87 12.06 2.87C11.72 2.87 11.38 2.96 11.08 3.14C10.77 3.31 10.52 3.56 10.34 3.86H10.29Z" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" />
</svg>
) : (
<svg width="22" height="22" viewBox="0 0 24 24" fill="none">
<path d="M12 8V12M12 16H12.01M22 12C22 17.52 17.52 22 12 22C6.48 22 2 17.52 2 12C2 6.48 6.48 2 12 2C17.52 2 22 6.48 22 12Z" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" />
</svg>
)}
</div>
<h3
className="flex-1 text-xl font-bold pt-1.5"
style={{ color: 'var(--text-strong)' }}
>
{title}
</h3>
<button
onClick={onClose}
className="shrink-0 w-8 h-8 -mt-1 -mr-1 rounded-lg hover:bg-[var(--row-hover-bg)] flex items-center justify-center text-xl leading-none"
style={{ color: 'var(--text-dim)' }}
aria-label="닫기"
>
×
</button>
</div>
<div className="px-7 pt-4 pb-7">
<p
className="text-lg leading-relaxed whitespace-pre-line"
style={{ color: 'var(--text-muted)' }}
>
{description}
</p>
</div>
<div
className="flex gap-2 px-7 py-4 border-t"
style={{ borderColor: 'var(--panel-border)' }}
>
<button
onClick={onClose}
className="flex-1 rounded-lg border px-4 h-11 text-sm font-medium hover:bg-[var(--btn-bg-hover)] hover:border-[var(--btn-border-hover)]"
style={{
background: 'var(--btn-bg)',
borderColor: 'var(--btn-border)',
color: 'var(--text-emphasis)',
}}
>
{cancelText}
</button>
<button
onClick={onConfirm}
disabled={loading}
className="flex-1 rounded-lg px-4 h-11 text-sm font-semibold disabled:opacity-50"
style={{
background: destructive ? 'var(--btn-danger-bg)' : 'var(--btn-primary-bg)',
color: destructive ? 'var(--btn-primary-text)' : 'var(--btn-primary-text)',
boxShadow: destructive ? 'var(--btn-danger-shadow)' : 'var(--btn-primary-shadow)',
}}
onMouseEnter={(e) => {
e.currentTarget.style.background = destructive ? 'var(--btn-danger-bg-hover)' : 'var(--btn-primary-bg-hover)'
}}
onMouseLeave={(e) => {
e.currentTarget.style.background = destructive ? 'var(--btn-danger-bg)' : 'var(--btn-primary-bg)'
}}
>
{loading ? '처리 중...' : confirmText}
</button>
</div>
</motion.div>
</motion.div>
)}
</AnimatePresence>
)
}