1- import React from 'react' ;
1+ import React , { useEffect } from 'react' ;
22import { motion , AnimatePresence } from 'framer-motion' ;
3- import { XIcon , ArrowSquareOutIcon } from '@phosphor-icons/react' ;
4- import GenerativeArt from './GenerativeArt' ;
3+ import { XIcon } from '@phosphor-icons/react' ;
54
6- const BrutalistModal = ( {
7- isOpen ,
8- onClose ,
9- item ,
10- children
11- } ) => {
12- if ( ! item ) return null ;
5+ const BrutalistModal = ( { isOpen , onClose , title , children } ) => {
6+ useEffect ( ( ) => {
7+ const handleKeyDown = ( event ) => {
8+ if ( event . key === 'Escape' && isOpen ) {
9+ onClose ( ) ;
10+ }
11+ } ;
1312
14- const title = item . label || item . title ;
15- const description = item . description ;
16- const url = item . url ;
13+ if ( isOpen ) {
14+ document . addEventListener ( 'keydown' , handleKeyDown ) ;
15+ document . body . style . overflow = 'hidden' ;
16+ } else {
17+ document . removeEventListener ( 'keydown' , handleKeyDown ) ;
18+ document . body . style . overflow = '' ;
19+ }
20+
21+ return ( ) => {
22+ document . removeEventListener ( 'keydown' , handleKeyDown ) ;
23+ document . body . style . overflow = '' ;
24+ } ;
25+ } , [ isOpen , onClose ] ) ;
1726
1827 return (
1928 < AnimatePresence >
2029 { isOpen && (
21- < div className = "fixed inset-0 z-[100] flex items-center justify-center p-4 md:p-12" >
22- { /* Backdrop */ }
30+ < div className = "fixed inset-0 z-[1000] flex items-center justify-center p-4" >
2331 < motion . div
2432 initial = { { opacity : 0 } }
2533 animate = { { opacity : 1 } }
2634 exit = { { opacity : 0 } }
2735 onClick = { onClose }
28- className = "absolute inset-0 bg-black/90 backdrop-blur-xl "
36+ className = "absolute inset-0 bg-black/80 backdrop-blur-sm "
2937 />
3038
31- { /* Modal Container */ }
3239 < motion . div
33- initial = { { opacity : 0 , scale : 0.95 , y : 40 } }
40+ initial = { { opacity : 0 , scale : 0.95 , y : 20 } }
3441 animate = { { opacity : 1 , scale : 1 , y : 0 } }
35- exit = { { opacity : 0 , scale : 0.95 , y : 40 } }
36- className = "relative w-full max-w-4xl bg-[#050505] border border-white/20 rounded-sm shadow-2xl overflow-hidden flex flex-col md:flex-row h-full md:h-auto max-h-[90vh]"
42+ exit = { { opacity : 0 , scale : 0.95 , y : 20 } }
43+ transition = { { duration : 0.3 , ease : [ 0.23 , 1 , 0.32 , 1 ] } }
44+ className = "relative w-full max-w-xl bg-[#050505] border border-white/10 rounded-sm shadow-2xl overflow-hidden flex flex-col"
3745 onClick = { ( e ) => e . stopPropagation ( ) }
3846 >
39- { /* Left/Top side: Large Art */ }
40- < div className = "relative w-full md:w-1/2 h-64 md:h-auto border-b md:border-b-0 md:border-r border-white/20" >
41- { item . image ? (
42- < img src = { item . image } alt = { title } className = "w-full h-full object-cover transition-all duration-700" />
43- ) : (
44- < GenerativeArt seed = { "2" + title + "[]" } className = "w-full h-full" />
45- ) }
46- < div className = "absolute inset-0 bg-gradient-to-t md:bg-gradient-to-r from-[#050505] to-transparent opacity-60" />
47+ < div className = "flex items-center justify-between p-6 border-b border-white/10 bg-white/[0.02]" >
48+ < h2 className = "text-2xl font-black uppercase tracking-tighter text-white" >
49+ { title }
50+ </ h2 >
51+ < button
52+ onClick = { onClose }
53+ className = "p-2 text-gray-500 hover:text-emerald-500 hover:bg-white/5 rounded-sm transition-all"
54+ >
55+ < XIcon size = { 24 } weight = "bold" />
56+ </ button >
4757 </ div >
4858
49- { /* Right side: Content */ }
50- < div className = "flex-1 flex flex-col p-8 md:p-12 relative overflow-y-auto" >
51- { /* Decorative background logo */ }
52- < div className = "absolute top-0 right-0 p-12 opacity-[0.02] pointer-events-none select-none" >
53- < h1 className = "text-9xl font-black font-playfairDisplay leading-none" > FC</ h1 >
54- </ div >
55-
56- < div className = "flex justify-between items-start mb-12" >
57- < div className = "space-y-1" >
58- < div className = "h-1 w-12 bg-emerald-500 mb-4" />
59- < h2 className = "text-4xl md:text-5xl font-normal font-playfairDisplay tracking-tighter text-white uppercase leading-none break-all" >
60- { title }
61- </ h2 >
62- </ div >
63- < button
64- onClick = { onClose }
65- className = "p-2 text-gray-500 hover:text-white transition-colors"
66- >
67- < XIcon weight = "bold" size = { 32 } />
68- </ button >
69- </ div >
70-
71- { children ? (
72- < div className = "flex-grow" >
73- { children }
74- </ div >
75- ) : (
76- < >
77- < div className = "flex-grow space-y-8" >
78- < p className = "text-xl md:text-2xl text-gray-300 font-arvo leading-relaxed" >
79- { description }
80- </ p >
81- { item . author && (
82- < div className = "pt-4 flex items-center gap-3" >
83- < div className = "w-8 h-px bg-white/20" />
84- < span className = "text-xs font-mono uppercase tracking-[0.4em] text-gray-500" >
85- Authored by // { item . author }
86- </ span >
87- </ div >
88- ) }
89- </ div >
90-
91- { url && url !== '#' && (
92- < div className = "mt-12" >
93- < a
94- href = { url }
95- target = "_blank"
96- rel = "noopener noreferrer"
97- className = "group inline-flex items-center gap-4 bg-white text-black px-8 py-5 font-mono font-black text-xs uppercase tracking-[0.4em] hover:bg-emerald-400 transition-all w-full md:w-auto"
98- >
99- < span > { item . actionLabel || "Visit" } </ span >
100- < ArrowSquareOutIcon weight = "bold" size = { 20 } />
101- </ a >
102- </ div >
103- ) }
104- </ >
105- ) }
106-
107- { /* Grid corner markers */ }
108- < div className = "absolute bottom-0 right-0 w-4 h-4 border-b border-r border-white/20 m-4" />
109- < div className = "absolute bottom-0 right-6 w-1 h-1 bg-emerald-500 m-4 rounded-full animate-pulse" />
59+ < div className = "p-8 max-h-[70vh] overflow-y-auto scrollbar-hide text-gray-300 font-mono text-sm leading-relaxed" >
60+ { children }
11061 </ div >
62+
63+ < div className = "h-1 w-full bg-gradient-to-r from-emerald-500/0 via-emerald-500/50 to-emerald-500/0 opacity-30" />
11164 </ motion . div >
11265 </ div >
11366 ) }
11467 </ AnimatePresence >
11568 ) ;
11669} ;
11770
118- export default BrutalistModal ;
71+ export default BrutalistModal ;
0 commit comments