@@ -7,9 +7,12 @@ interface Props {
77 selectedRunId : string | null ;
88 onSelectRun : ( id : string ) => void ;
99 onNewRun : ( ) => void ;
10+ isMobile ?: boolean ;
11+ isOpen ?: boolean ;
12+ onClose ?: ( ) => void ;
1013}
1114
12- export default function Sidebar ( { runs, selectedRunId, onSelectRun, onNewRun } : Props ) {
15+ export default function Sidebar ( { runs, selectedRunId, onSelectRun, onNewRun, isMobile , isOpen , onClose } : Props ) {
1316 const { theme, toggleTheme } = useTheme ( ) ;
1417
1518 const sorted = [ ...runs ] . sort (
@@ -18,6 +21,104 @@ export default function Sidebar({ runs, selectedRunId, onSelectRun, onNewRun }:
1821 new Date ( a . start_time ?? 0 ) . getTime ( ) ,
1922 ) ;
2023
24+ // On mobile: hidden unless open, renders as overlay drawer
25+ if ( isMobile ) {
26+ if ( ! isOpen ) return null ;
27+ return (
28+ < >
29+ { /* Backdrop */ }
30+ < div
31+ className = "fixed inset-0 z-50"
32+ style = { { background : "rgba(0,0,0,0.5)" } }
33+ onClick = { onClose }
34+ />
35+ { /* Drawer */ }
36+ < aside className = "fixed inset-y-0 left-0 z-50 w-64 bg-[var(--sidebar-bg)] border-r border-[var(--border)] flex flex-col" >
37+ { /* Header */ }
38+ < div className = "px-3 h-10 border-b border-[var(--border)] flex items-center justify-between" >
39+ < button
40+ onClick = { onNewRun }
41+ className = "flex items-center gap-1.5 cursor-pointer transition-opacity hover:opacity-80"
42+ >
43+ < svg width = "16" height = "16" viewBox = "0 0 24 24" fill = "none" >
44+ < rect width = "24" height = "24" rx = "4" fill = "var(--accent)" />
45+ < text x = "12" y = "17" textAnchor = "middle" fill = "white" fontSize = "14" fontWeight = "700" fontFamily = "Arial, sans-serif" > U</ text >
46+ </ svg >
47+ < span
48+ className = "text-[11px] uppercase tracking-widest font-semibold"
49+ style = { { color : "var(--text-muted)" } }
50+ >
51+ Dev Console
52+ </ span >
53+ </ button >
54+ < div className = "flex items-center gap-1" >
55+ < button
56+ onClick = { toggleTheme }
57+ className = "w-6 h-6 flex items-center justify-center rounded cursor-pointer transition-colors"
58+ style = { { color : "var(--text-muted)" } }
59+ title = { `Switch to ${ theme === "dark" ? "light" : "dark" } theme` }
60+ >
61+ < svg width = "14" height = "14" viewBox = "0 0 24 24" fill = "none" stroke = "currentColor" strokeWidth = "2" strokeLinecap = "round" strokeLinejoin = "round" >
62+ { theme === "dark" ? (
63+ < > < circle cx = "12" cy = "12" r = "5" /> < line x1 = "12" y1 = "1" x2 = "12" y2 = "3" /> < line x1 = "12" y1 = "21" x2 = "12" y2 = "23" /> < line x1 = "4.22" y1 = "4.22" x2 = "5.64" y2 = "5.64" /> < line x1 = "18.36" y1 = "18.36" x2 = "19.78" y2 = "19.78" /> < line x1 = "1" y1 = "12" x2 = "3" y2 = "12" /> < line x1 = "21" y1 = "12" x2 = "23" y2 = "12" /> < line x1 = "4.22" y1 = "19.78" x2 = "5.64" y2 = "18.36" /> < line x1 = "18.36" y1 = "5.64" x2 = "19.78" y2 = "4.22" /> </ >
64+ ) : (
65+ < path d = "M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z" />
66+ ) }
67+ </ svg >
68+ </ button >
69+ { /* Close button */ }
70+ < button
71+ onClick = { onClose }
72+ className = "w-6 h-6 flex items-center justify-center rounded cursor-pointer transition-colors"
73+ style = { { color : "var(--text-muted)" } }
74+ >
75+ < svg width = "14" height = "14" viewBox = "0 0 24 24" fill = "none" stroke = "currentColor" strokeWidth = "2" strokeLinecap = "round" >
76+ < line x1 = "18" y1 = "6" x2 = "6" y2 = "18" />
77+ < line x1 = "6" y1 = "6" x2 = "18" y2 = "18" />
78+ </ svg >
79+ </ button >
80+ </ div >
81+ </ div >
82+
83+ { /* New Run */ }
84+ < button
85+ onClick = { onNewRun }
86+ className = "mx-3 mt-2.5 mb-1 px-2 py-1.5 text-[10px] uppercase tracking-wider font-semibold rounded border border-[var(--border)] bg-transparent transition-colors cursor-pointer"
87+ style = { { color : "var(--text-muted)" } }
88+ >
89+ + New Run
90+ </ button >
91+
92+ { /* Runs label */ }
93+ < div
94+ className = "px-3 pt-3 pb-1 text-[10px] uppercase tracking-widest font-semibold"
95+ style = { { color : "var(--text-muted)" } }
96+ >
97+ History
98+ </ div >
99+
100+ { /* Run list */ }
101+ < div className = "flex-1 overflow-y-auto" >
102+ { sorted . map ( ( run ) => (
103+ < RunHistoryItem
104+ key = { run . id }
105+ run = { run }
106+ isSelected = { run . id === selectedRunId }
107+ onClick = { ( ) => onSelectRun ( run . id ) }
108+ />
109+ ) ) }
110+ { sorted . length === 0 && (
111+ < p className = "text-xs px-3 py-4 text-center" style = { { color : "var(--text-muted)" } } >
112+ No runs yet
113+ </ p >
114+ ) }
115+ </ div >
116+ </ aside >
117+ </ >
118+ ) ;
119+ }
120+
121+ // Desktop: unchanged
21122 return (
22123 < aside className = "w-44 bg-[var(--sidebar-bg)] border-r border-[var(--border)] flex flex-col" >
23124 { /* Header */ }
0 commit comments