Skip to content

Commit 50f9b18

Browse files
committed
feat(terracotta): add TerracottaModal component
1 parent e443cf6 commit 50f9b18

1 file changed

Lines changed: 75 additions & 0 deletions

File tree

src/components/TerracottaModal.jsx

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
import React, { useEffect } from 'react';
2+
import { motion, AnimatePresence } from 'framer-motion';
3+
import { XIcon } from '@phosphor-icons/react';
4+
5+
const TerracottaModal = ({
6+
isOpen,
7+
onClose,
8+
title,
9+
children,
10+
maxWidth = 'max-w-xl',
11+
}) => {
12+
useEffect(() => {
13+
const handleKeyDown = (event) => {
14+
if (event.key === 'Escape' && isOpen) onClose();
15+
};
16+
17+
if (isOpen) {
18+
document.addEventListener('keydown', handleKeyDown);
19+
document.body.style.overflow = 'hidden';
20+
} else {
21+
document.removeEventListener('keydown', handleKeyDown);
22+
document.body.style.overflow = '';
23+
}
24+
25+
return () => {
26+
document.removeEventListener('keydown', handleKeyDown);
27+
document.body.style.overflow = '';
28+
};
29+
}, [isOpen, onClose]);
30+
31+
return (
32+
<AnimatePresence>
33+
{isOpen && (
34+
<div className="fixed inset-0 z-[1000] flex items-center justify-center p-4">
35+
<motion.div
36+
initial={{ opacity: 0 }}
37+
animate={{ opacity: 1 }}
38+
exit={{ opacity: 0 }}
39+
onClick={onClose}
40+
className="absolute inset-0 bg-[#1A1613]/60 backdrop-blur-sm"
41+
/>
42+
43+
<motion.div
44+
initial={{ opacity: 0, scale: 0.95, y: 20 }}
45+
animate={{ opacity: 1, scale: 1, y: 0 }}
46+
exit={{ opacity: 0, scale: 0.95, y: 20 }}
47+
transition={{ duration: 0.3, ease: [0.23, 1, 0.32, 1] }}
48+
className={`relative w-full ${maxWidth} bg-[#F3ECE0] border border-[#1A161320] rounded-sm shadow-[0_40px_80px_-40px_#1A161360] overflow-hidden flex flex-col`}
49+
onClick={(e) => e.stopPropagation()}
50+
>
51+
<div className="flex items-center justify-between p-6 border-b border-[#1A161320] bg-[#E8DECE]/60">
52+
<h2 className="text-2xl font-playfairDisplay italic tracking-tight text-[#1A1613]">
53+
{title}
54+
</h2>
55+
<button
56+
onClick={onClose}
57+
className="p-2 text-[#2E2620]/60 hover:text-[#9E4A2F] hover:bg-[#E8DECE] rounded-sm transition-all"
58+
>
59+
<XIcon size={24} weight="bold" />
60+
</button>
61+
</div>
62+
63+
<div className="p-8 max-h-[70vh] overflow-y-auto scrollbar-hide text-[#2E2620] font-mono text-sm leading-relaxed">
64+
{children}
65+
</div>
66+
67+
<div className="h-1 w-full bg-gradient-to-r from-[#C96442]/0 via-[#C96442]/60 to-[#C96442]/0 opacity-40" />
68+
</motion.div>
69+
</div>
70+
)}
71+
</AnimatePresence>
72+
);
73+
};
74+
75+
export default TerracottaModal;

0 commit comments

Comments
 (0)