1+ 'use client' ;
2+
3+ import React , { useState , useEffect } from 'react' ;
4+
5+ // --- SVG ICONS COMPONENTS ---
6+
7+ const IconFloppy = ( ) => (
8+ < svg viewBox = "0 0 24 24" className = "w-10 h-10 fill-current text-black" >
9+ < path d = "M2 2h20v20H2V2zm2 2v6h16V4H4zm4 2h8v2H8V6zm-4 14h16v-8H4v8zm2-2h12v-4H6v4z" />
10+ </ svg >
11+ ) ;
12+
13+ const IconFolder = ( ) => (
14+ < svg viewBox = "0 0 24 24" className = "w-12 h-10 fill-none stroke-black stroke-2" >
15+ < path d = "M2 4h6l2 2h12v14H2V4z" />
16+ < line x1 = "2" y1 = "8" x2 = "22" y2 = "8" />
17+ </ svg >
18+ ) ;
19+
20+ const IconTrash = ( ) => (
21+ < svg viewBox = "0 0 24 24" className = "w-10 h-12 fill-none stroke-black stroke-2" >
22+ < path d = "M4 6h16M8 6V4h8v2M6 6v14h12V6" />
23+ < line x1 = "10" y1 = "10" x2 = "10" y2 = "16" />
24+ < line x1 = "14" y1 = "10" x2 = "14" y2 = "16" />
25+ < line x1 = "6" y1 = "9" x2 = "18" y2 = "9" />
26+ </ svg >
27+ ) ;
28+
29+ const IconHardDisk = ( ) => (
30+ < svg viewBox = "0 0 24 24" className = "w-10 h-10 fill-none stroke-black stroke-2" >
31+ < rect x = "2" y = "4" width = "20" height = "12" />
32+ < line x1 = "2" y1 = "10" x2 = "22" y2 = "10" />
33+ < rect x = "4" y = "12" width = "4" height = "2" fill = "black" />
34+ < path d = "M2 16h20l-2 4H4l-2-4z" />
35+ </ svg >
36+ ) ;
37+
38+ const IconBee = ( ) => (
39+ < svg viewBox = "0 0 24 24" className = "w-8 h-8 fill-black" >
40+ < path d = "M4 8h4v2H4zm6 0h4v2h-4zm6 0h2v4h-2v-2h-2v2h-4v-2H8v2H6v-2H4v6h16V8z" />
41+ < path d = "M6 12h2v2H6zm4 0h4v2h-4zm6 0h2v2h-2z" fill = "white" />
42+ </ svg >
43+ ) ;
44+
45+ // --- UI COMPONENTS ---
46+
47+ const DitherPattern = ( ) => (
48+ < div className = "w-full h-full opacity-30" style = { {
49+ backgroundImage : 'radial-gradient(black 1px, transparent 1px)' ,
50+ backgroundSize : '3px 3px'
51+ } } > </ div >
52+ ) ;
53+
54+ const WindowFrame = ( { title, children, className, width, height, zIndex = 10 } : any ) => (
55+ < div
56+ className = { `absolute bg-white border-2 border-black shadow-[4px_4px_0px_rgba(0,0,0,0.2)] ${ className } ` }
57+ style = { { width, height, zIndex } }
58+ >
59+ { /* Title Bar */ }
60+ < div className = "h-6 border-b-2 border-black flex justify-between items-center bg-white" >
61+ < div className = "w-6 h-6 border-r-2 border-black flex items-center justify-center relative bg-white" >
62+ < div className = "absolute inset-0 p-1" > < div className = "w-full h-full border border-black bg-white relative" > < div className = "absolute top-0 left-0 w-full h-0.5 bg-black" > </ div > </ div > </ div >
63+ </ div >
64+ < div className = "flex-1 h-full flex items-center justify-center relative overflow-hidden" >
65+ < DitherPattern />
66+ < span className = "bg-white px-2 relative z-10 font-bold text-lg tracking-widest uppercase" > { title } </ span >
67+ </ div >
68+ < div className = "w-6 h-6 border-l-2 border-black flex items-center justify-center" >
69+ < div className = "w-0 h-0 border-l-[6px] border-l-transparent border-r-[6px] border-r-transparent border-b-[8px] border-b-black" > </ div >
70+ </ div >
71+ </ div >
72+
73+ { /* Content Area */ }
74+ < div className = "relative h-[calc(100%-24px)] w-full overflow-hidden" >
75+ { children }
76+
77+ { /* Scroll Bars (Decoration) */ }
78+ < div className = "absolute right-0 top-0 w-6 h-full border-l-2 border-black flex flex-col justify-between bg-white" >
79+ < div className = "h-6 border-b-2 border-black flex items-center justify-center" >
80+ < div className = "w-0 h-0 border-l-[4px] border-l-transparent border-r-[4px] border-r-transparent border-b-[6px] border-b-black" > </ div >
81+ </ div >
82+ < div className = "flex-1 relative" > < DitherPattern /> </ div >
83+ < div className = "h-6 border-t-2 border-black flex items-center justify-center" >
84+ < div className = "w-0 h-0 border-l-[4px] border-l-transparent border-r-[4px] border-r-transparent border-t-[6px] border-t-black" > </ div >
85+ </ div >
86+ </ div >
87+
88+ < div className = "absolute bottom-0 left-0 w-full h-6 border-t-2 border-black flex justify-between bg-white" >
89+ < div className = "w-6 border-r-2 border-black flex items-center justify-center" >
90+ < div className = "w-0 h-0 border-t-[4px] border-t-transparent border-b-[4px] border-b-transparent border-r-[6px] border-r-black" > </ div >
91+ </ div >
92+ < div className = "flex-1 relative" > < DitherPattern /> </ div >
93+ < div className = "w-6 border-l-2 border-black bg-black" > </ div > { /* Corner box */ }
94+ </ div >
95+ </ div >
96+ </ div >
97+ ) ;
98+
99+ // --- CLOCK LOGIC ---
100+
101+ const AnalogClock = ( ) => {
102+ const [ time , setTime ] = useState ( new Date ( ) ) ;
103+ const [ mounted , setMounted ] = useState ( false ) ;
104+
105+ useEffect ( ( ) => {
106+ setMounted ( true ) ;
107+ const timer = setInterval ( ( ) => setTime ( new Date ( ) ) , 1000 ) ;
108+ return ( ) => clearInterval ( timer ) ;
109+ } , [ ] ) ;
110+
111+ if ( ! mounted ) return null ; // Prevent hydration mismatch
112+
113+ const seconds = time . getSeconds ( ) ;
114+ const minutes = time . getMinutes ( ) ;
115+ const hours = time . getHours ( ) ;
116+
117+ const secondDeg = seconds * 6 ;
118+ const minuteDeg = minutes * 6 + seconds * 0.1 ;
119+ const hourDeg = ( hours % 12 ) * 30 + minutes * 0.5 ;
120+
121+ return (
122+ < div className = "relative w-full h-full bg-white overflow-hidden" >
123+ { /* Grid Background */ }
124+ < div className = "absolute inset-0" style = { {
125+ backgroundImage : `linear-gradient(black 1px, transparent 1px), linear-gradient(90deg, black 1px, transparent 1px)` ,
126+ backgroundSize : '20px 20px' ,
127+ opacity : 0.15
128+ } } > </ div >
129+
130+ { /* Clock Face Numbers */ }
131+ < div className = "absolute inset-0 rounded-full m-4 border-2 border-black bg-white shadow-sm flex items-center justify-center" >
132+ { [ ...Array ( 12 ) ] . map ( ( _ , i ) => {
133+ const num = i + 1 ;
134+ const rotation = num * 30 ;
135+ // Simple math to position numbers in a circle
136+ const angle = ( rotation - 90 ) * ( Math . PI / 180 ) ;
137+ const radius = 42 ; // percentage
138+ const x = 50 + radius * Math . cos ( angle ) ;
139+ const y = 50 + radius * Math . sin ( angle ) ;
140+
141+ return (
142+ < div key = { num } className = "absolute font-bold text-xl" style = { { left : `${ x } %` , top : `${ y } %` , transform : 'translate(-50%, -50%)' } } >
143+ { num }
144+ </ div >
145+ ) ;
146+ } ) }
147+
148+ { /* Center Nut */ }
149+ < div className = "absolute w-4 h-4 bg-yellow-600 rounded-full border border-black z-50 shadow-md" > </ div >
150+
151+ { /* Hands */ }
152+ { /* Hour */ }
153+ < div className = "absolute bg-black z-20 rounded-full origin-bottom"
154+ style = { {
155+ width : '6px' ,
156+ height : '25%' ,
157+ bottom : '50%' ,
158+ left : 'calc(50% - 3px)' ,
159+ transform : `rotate(${ hourDeg } deg)`
160+ } } >
161+ < div className = "absolute -top-2 -left-1 w-0 h-0 border-l-[5px] border-l-transparent border-r-[5px] border-r-transparent border-b-[10px] border-b-black" > </ div >
162+ </ div >
163+
164+ { /* Minute */ }
165+ < div className = "absolute bg-black z-30 rounded-full origin-bottom"
166+ style = { {
167+ width : '4px' ,
168+ height : '35%' ,
169+ bottom : '50%' ,
170+ left : 'calc(50% - 2px)' ,
171+ transform : `rotate(${ minuteDeg } deg)`
172+ } } >
173+ < div className = "absolute -top-2 -left-1 w-0 h-0 border-l-[4px] border-l-transparent border-r-[4px] border-r-transparent border-b-[8px] border-b-black" > </ div >
174+ </ div >
175+
176+ { /* Second */ }
177+ < div className = "absolute bg-black z-40 origin-bottom"
178+ style = { {
179+ width : '1px' ,
180+ height : '40%' ,
181+ bottom : '50%' ,
182+ left : '50%' ,
183+ transform : `rotate(${ secondDeg } deg)`
184+ } } > </ div >
185+ </ div >
186+ </ div >
187+ ) ;
188+ } ;
189+
190+ // --- MAIN PAGE ---
191+
192+ export default function RetroDesktop ( ) {
193+ return (
194+ < div className = "min-h-screen flex items-center justify-center bg-neutral-100 p-4" >
195+ { /* The Main "Board" / Monitor */ }
196+ < div className = "relative w-[500px] h-[700px] bg-[#2fa046] border border-black shadow-2xl overflow-hidden select-none font-vt323 text-black" >
197+
198+ { /* Top Menu Bar */ }
199+ < div className = "absolute top-0 left-0 right-0 h-8 bg-white border-b-2 border-black flex items-center px-2 z-50 text-xl" >
200+ < div className = "mr-6 font-bold cursor-pointer hover:underline" > Desk</ div >
201+ < div className = "bg-black text-white px-3 h-full flex items-center cursor-pointer relative group" >
202+ File
203+ { /* Dropdown Menu */ }
204+ < div className = "absolute top-8 left-0 bg-white border-2 border-black text-black w-64 shadow-[4px_4px_0px_rgba(0,0,0,0.5)] p-1 leading-tight" >
205+ < div className = "px-4 py-1 hover:bg-black hover:text-white cursor-pointer" > Open</ div >
206+ < div className = "px-4 py-1 hover:bg-black hover:text-white cursor-pointer font-bold" > Show Info...</ div >
207+ < div className = "h-[1px] bg-black my-1 border-b border-black border-dotted" > </ div >
208+ < div className = "px-4 py-1 hover:bg-black hover:text-white cursor-pointer font-bold" > New Folder...</ div >
209+ < div className = "px-4 py-1 hover:bg-black hover:text-white cursor-pointer" > Close</ div >
210+ < div className = "px-4 py-1 hover:bg-black hover:text-white cursor-pointer font-bold" > Close Window</ div >
211+ < div className = "h-[1px] bg-black my-1 border-b border-black border-dotted" > </ div >
212+ < div className = "px-4 py-1 text-gray-400 pointer-events-none" > Format...</ div >
213+ </ div >
214+ </ div >
215+ < div className = "ml-6 cursor-pointer hover:underline" > View</ div >
216+ < div className = "ml-6 cursor-pointer hover:underline" > Options</ div >
217+ </ div >
218+
219+ { /* Desktop Icons */ }
220+ < div className = "absolute top-16 left-4 flex flex-col items-center gap-1" >
221+ < IconFloppy />
222+ < span className = "bg-white px-1 text-sm border border-black" > FLOPPY A</ span >
223+ </ div >
224+
225+ < div className = "absolute top-40 left-4 flex flex-col items-center gap-1" >
226+ < IconFloppy />
227+ < span className = "bg-black text-white px-1 text-sm" > FLOPPY DISK</ span >
228+ </ div >
229+
230+ < div className = "absolute bottom-4 left-4 flex flex-col items-center gap-1 z-0" >
231+ < IconTrash />
232+ < span className = "bg-white px-1 text-sm border border-black" > TRASH</ span >
233+ </ div >
234+
235+ < div className = "absolute bottom-4 right-4 flex flex-col items-center gap-1 z-0" >
236+ < IconHardDisk />
237+ < span className = "bg-white px-1 text-sm border border-black" > HARD DISK</ span >
238+ </ div >
239+
240+ < div className = "absolute top-1/2 left-16 z-0 opacity-50" >
241+ < IconBee />
242+ </ div >
243+
244+ { /* Background Window (Files) */ }
245+ < WindowFrame
246+ title = ""
247+ className = "top-28 right-[-20px]"
248+ width = "300px"
249+ height = "200px"
250+ zIndex = { 5 }
251+ >
252+ < div className = "p-4 flex justify-around pt-8" >
253+ < div className = "flex flex-col items-center" >
254+ < IconFolder />
255+ < span className = "mt-1 uppercase" > Space</ span >
256+ </ div >
257+ < div className = "flex flex-col items-center" >
258+ < IconFolder />
259+ < span className = "mt-1 uppercase" > Time</ span >
260+ </ div >
261+ </ div >
262+ < div className = "absolute top-0 left-0 w-full h-6 border-b border-black bg-white px-2" >
263+ { /* Fake Path */ }
264+ C:\...
265+ </ div >
266+ </ WindowFrame >
267+
268+ { /* Main Clock Window */ }
269+ < WindowFrame
270+ title = "CLOCK"
271+ className = "top-56 left-1/2 -translate-x-1/2"
272+ width = "280px"
273+ height = "280px"
274+ zIndex = { 20 }
275+ >
276+ < div className = "w-[calc(100%-24px)] h-[calc(100%-24px)] relative" >
277+ < AnalogClock />
278+ </ div >
279+ </ WindowFrame >
280+
281+ { /* Tic Tac Toe Window */ }
282+ < WindowFrame
283+ title = "by" // Trying to match the clipped title in the image
284+ className = "bottom-20 left-2"
285+ width = "240px"
286+ height = "180px"
287+ zIndex = { 15 }
288+ >
289+ < div className = "flex h-full w-[calc(100%-24px)]" >
290+ { /* Game Board */ }
291+ < div className = "w-2/3 border-r-2 border-black flex items-center justify-center p-2 relative" >
292+ { /* Grid Lines */ }
293+ < div className = "absolute w-full h-2 bg-black top-1/3" > </ div >
294+ < div className = "absolute w-full h-2 bg-black top-2/3" > </ div >
295+ < div className = "absolute h-full w-2 bg-black left-1/3" > </ div >
296+ < div className = "absolute h-full w-2 bg-black left-2/3" > </ div >
297+
298+ { /* X and 0 placeholder */ }
299+ < span className = "absolute top-[10%] left-[60%] font-bold text-2xl" > 0</ span >
300+ < span className = "absolute top-[45%] left-[45%] font-bold text-2xl" > X</ span >
301+ </ div >
302+
303+ { /* Sidebar Buttons */ }
304+ < div className = "w-1/3 flex flex-col bg-[#c41c1c] p-1 gap-1 border-l-2 border-black relative" >
305+ < DitherPattern />
306+ { [ 'Start' , 'Setup' , 'Score' , 'Info' ] . map ( ( text ) => (
307+ < div key = { text } className = "bg-white border-2 border-black text-center text-sm cursor-pointer hover:bg-gray-200 z-10 relative shadow-sm" >
308+ { text }
309+ </ div >
310+ ) ) }
311+ </ div >
312+ </ div >
313+ </ WindowFrame >
314+
315+ </ div >
316+ </ div >
317+ ) ;
318+ }
0 commit comments