wuhp commited on
Commit
05e0780
·
verified ·
1 Parent(s): 337becc

Update components/Sidebar.tsx

Browse files
Files changed (1) hide show
  1. components/Sidebar.tsx +127 -108
components/Sidebar.tsx CHANGED
@@ -2,7 +2,7 @@
2
  import React, { useState } from 'react';
3
  import { LAYER_DEFINITIONS } from '../constants';
4
  import { LayerType } from '../types';
5
- import { Box, Sparkles, LayoutTemplate, Circle, Search, X } from 'lucide-react';
6
 
7
  interface SidebarProps {
8
  onOpenAIBuilder: () => void;
@@ -12,6 +12,7 @@ interface SidebarProps {
12
 
13
  const Sidebar: React.FC<SidebarProps> = ({ onOpenAIBuilder, onSelectTemplate, isConnected }) => {
14
  const [searchQuery, setSearchQuery] = useState('');
 
15
 
16
  const onDragStart = (event: React.DragEvent, layerType: LayerType) => {
17
  event.dataTransfer.setData('application/reactflow', layerType);
@@ -19,7 +20,13 @@ const Sidebar: React.FC<SidebarProps> = ({ onOpenAIBuilder, onSelectTemplate, is
19
  };
20
 
21
  const categories = Array.from(new Set(Object.values(LAYER_DEFINITIONS).map(l => l.category)));
22
- const categoryOrder = ['Core', 'Convolution', 'Recurrent', 'Transformer', 'Normalization', 'GenAI', 'Utility', 'Merge'];
 
 
 
 
 
 
23
  categories.sort((a, b) => {
24
  const idxA = categoryOrder.indexOf(a);
25
  const idxB = categoryOrder.indexOf(b);
@@ -35,124 +42,136 @@ const Sidebar: React.FC<SidebarProps> = ({ onOpenAIBuilder, onSelectTemplate, is
35
  );
36
 
37
  return (
38
- <aside className="w-64 bg-slate-900 border-r border-slate-800 flex flex-col h-full z-10">
39
- <div className="p-4 border-b border-slate-800 bg-slate-900 space-y-4">
40
- <div>
41
- <h1 className="text-xl font-bold bg-gradient-to-r from-blue-400 to-violet-400 bg-clip-text text-transparent">
42
- Architecture Agents
43
- </h1>
44
- <p className="text-xs text-slate-500 mt-1">AI-Powered Model Builder</p>
45
- </div>
46
-
47
- <div className="grid grid-cols-2 gap-2">
48
- <button
49
- onClick={onOpenAIBuilder}
50
- className="flex flex-col items-center justify-center p-2 bg-purple-500/10 hover:bg-purple-500/20 border border-purple-500/30 rounded-lg text-purple-300 transition-colors group"
51
- >
52
- <Sparkles size={18} className="mb-1 group-hover:scale-110 transition-transform" />
53
- <span className="text-[10px] font-bold">AI Builder</span>
54
- </button>
55
- <button
56
- onClick={() => onSelectTemplate('menu')}
57
- className="flex flex-col items-center justify-center p-2 bg-blue-500/10 hover:bg-blue-500/20 border border-blue-500/30 rounded-lg text-blue-300 transition-colors group"
58
- >
59
- <LayoutTemplate size={18} className="mb-1 group-hover:scale-110 transition-transform" />
60
- <span className="text-[10px] font-bold">Templates</span>
61
- </button>
62
- </div>
63
 
64
- {/* Search Bar */}
65
- <div className="relative">
66
- <Search className="absolute left-3 top-2.5 text-slate-500" size={14} />
67
- <input
68
- type="text"
69
- placeholder="Search layers..."
70
- className="w-full bg-slate-950 border border-slate-700 rounded-lg pl-9 pr-8 py-2 text-xs text-slate-200 focus:outline-none focus:border-blue-500 transition-colors placeholder-slate-600"
71
- value={searchQuery}
72
- onChange={(e) => setSearchQuery(e.target.value)}
73
- />
74
- {searchQuery && (
75
  <button
76
- onClick={() => setSearchQuery('')}
77
- className="absolute right-2 top-2 text-slate-500 hover:text-slate-300"
78
  >
79
- <X size={14} />
 
80
  </button>
81
- )}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
82
  </div>
83
- </div>
84
-
85
- <div className="flex-1 overflow-y-auto p-4 space-y-6 scrollbar-thin scrollbar-thumb-slate-700">
86
 
87
- {searchQuery ? (
88
- // Search Results View
89
- <div className="space-y-2">
90
- <h3 className="text-xs font-semibold text-slate-500 uppercase tracking-widest mb-3">
91
- Search Results ({filteredLayers.length})
92
- </h3>
93
- {filteredLayers.length > 0 ? (
94
- filteredLayers.map(layer => (
95
- <div
96
- key={layer.type}
97
- className="bg-slate-800 hover:bg-slate-750 p-3 rounded border border-slate-700 cursor-grab active:cursor-grabbing transition-colors group relative overflow-hidden"
98
- onDragStart={(event) => onDragStart(event, layer.type)}
99
- draggable
100
- >
101
- <div className="flex items-center gap-3 relative z-10">
102
- <div className={`p-1.5 rounded transition-colors group-hover:bg-slate-900 bg-slate-900/50`}>
103
- <Box size={14} className="text-slate-400 group-hover:text-blue-400" />
104
- </div>
105
- <div>
106
- <div className="text-sm font-medium text-slate-200 group-hover:text-white">{layer.label}</div>
107
- <div className="text-xs text-slate-500 leading-tight group-hover:text-slate-400 line-clamp-2">{layer.description}</div>
 
 
 
108
  </div>
109
  </div>
 
 
 
 
110
  </div>
111
- ))
112
- ) : (
113
- <div className="text-center text-slate-500 py-8 text-xs italic">
114
- No layers found matching "{searchQuery}"
115
- </div>
116
- )}
117
- </div>
118
- ) : (
119
- // Categorized View
120
- categories.map(category => (
121
- <div key={category}>
122
- <h3 className="text-xs font-semibold text-slate-500 uppercase tracking-widest mb-3 flex items-center gap-2">
123
- {category}
124
- <div className="h-px flex-1 bg-slate-800"></div>
125
- </h3>
126
- <div className="grid grid-cols-1 gap-2">
127
- {Object.values(LAYER_DEFINITIONS)
128
- .filter(l => l.category === category)
129
- .map(layer => (
130
- <div
131
- key={layer.type}
132
- className="bg-slate-800 hover:bg-slate-750 p-3 rounded border border-slate-700 cursor-grab active:cursor-grabbing transition-colors group relative overflow-hidden"
133
- onDragStart={(event) => onDragStart(event, layer.type)}
134
- draggable
135
- >
136
- <div className="flex items-center gap-3 relative z-10">
137
- <div className={`p-1.5 rounded transition-colors group-hover:bg-slate-900 bg-slate-900/50`}>
138
- <Box size={14} className="text-slate-400 group-hover:text-blue-400" />
139
- </div>
140
- <div>
141
- <div className="text-sm font-medium text-slate-200 group-hover:text-white">{layer.label}</div>
142
- <div className="text-xs text-slate-500 leading-tight group-hover:text-slate-400">{layer.description}</div>
143
  </div>
144
  </div>
145
- </div>
146
- ))}
147
  </div>
148
- </div>
149
- ))
150
- )}
151
- </div>
152
-
153
- <div className="p-4 border-t border-slate-800 text-[10px] text-slate-500 text-center flex items-center justify-center gap-2">
154
- <span>v1.2.0 Powered by Gemini 2.5</span>
155
- <Circle size={8} className={isConnected ? "fill-emerald-500 text-emerald-500" : "fill-red-500 text-red-500"} />
156
  </div>
157
  </aside>
158
  );
 
2
  import React, { useState } from 'react';
3
  import { LAYER_DEFINITIONS } from '../constants';
4
  import { LayerType } from '../types';
5
+ import { Box, Sparkles, LayoutTemplate, Circle, Search, X, ChevronLeft, ChevronRight } from 'lucide-react';
6
 
7
  interface SidebarProps {
8
  onOpenAIBuilder: () => void;
 
12
 
13
  const Sidebar: React.FC<SidebarProps> = ({ onOpenAIBuilder, onSelectTemplate, isConnected }) => {
14
  const [searchQuery, setSearchQuery] = useState('');
15
+ const [isOpen, setIsOpen] = useState(true);
16
 
17
  const onDragStart = (event: React.DragEvent, layerType: LayerType) => {
18
  event.dataTransfer.setData('application/reactflow', layerType);
 
20
  };
21
 
22
  const categories = Array.from(new Set(Object.values(LAYER_DEFINITIONS).map(l => l.category)));
23
+ const categoryOrder = [
24
+ 'Core', 'Convolution', 'Recurrent', 'Transformer', 'Normalization', 'GenAI',
25
+ 'Video', 'Audio', '3D', 'Detection', 'OCR', 'Robotics',
26
+ 'Graph', 'Physics', 'Spiking', 'RL', 'Advanced',
27
+ 'Utility', 'Merge'
28
+ ];
29
+
30
  categories.sort((a, b) => {
31
  const idxA = categoryOrder.indexOf(a);
32
  const idxB = categoryOrder.indexOf(b);
 
42
  );
43
 
44
  return (
45
+ <aside className={`${isOpen ? 'w-64 border-r' : 'w-0 border-none'} bg-slate-900 border-slate-800 flex flex-col h-full z-20 transition-all duration-300 relative`}>
46
+ {/* Toggle Button */}
47
+ <button
48
+ onClick={() => setIsOpen(!isOpen)}
49
+ className="absolute -right-3 top-6 bg-slate-800 border border-slate-700 text-slate-400 p-0.5 rounded-full hover:text-white hover:bg-slate-700 cursor-pointer z-50 w-6 h-6 flex items-center justify-center shadow-md transition-transform"
50
+ title={isOpen ? "Collapse Sidebar" : "Expand Sidebar"}
51
+ >
52
+ {isOpen ? <ChevronLeft size={14} /> : <ChevronRight size={14} />}
53
+ </button>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
54
 
55
+ {/* Content Container */}
56
+ <div className={`flex flex-col h-full overflow-hidden ${!isOpen ? 'invisible opacity-0' : 'visible opacity-100'} transition-opacity duration-200`}>
57
+ <div className="p-4 border-b border-slate-800 bg-slate-900 space-y-4 min-w-[16rem]">
58
+ <div>
59
+ <h1 className="text-xl font-bold bg-gradient-to-r from-blue-400 to-violet-400 bg-clip-text text-transparent">
60
+ Architecture Agents
61
+ </h1>
62
+ <p className="text-xs text-slate-500 mt-1">AI-Powered Model Builder</p>
63
+ </div>
64
+
65
+ <div className="grid grid-cols-2 gap-2">
66
  <button
67
+ onClick={onOpenAIBuilder}
68
+ className="flex flex-col items-center justify-center p-2 bg-purple-500/10 hover:bg-purple-500/20 border border-purple-500/30 rounded-lg text-purple-300 transition-colors group"
69
  >
70
+ <Sparkles size={18} className="mb-1 group-hover:scale-110 transition-transform" />
71
+ <span className="text-[10px] font-bold">AI Builder</span>
72
  </button>
73
+ <button
74
+ onClick={() => onSelectTemplate('menu')}
75
+ className="flex flex-col items-center justify-center p-2 bg-blue-500/10 hover:bg-blue-500/20 border border-blue-500/30 rounded-lg text-blue-300 transition-colors group"
76
+ >
77
+ <LayoutTemplate size={18} className="mb-1 group-hover:scale-110 transition-transform" />
78
+ <span className="text-[10px] font-bold">Templates</span>
79
+ </button>
80
+ </div>
81
+
82
+ {/* Search Bar */}
83
+ <div className="relative">
84
+ <Search className="absolute left-3 top-2.5 text-slate-500" size={14} />
85
+ <input
86
+ type="text"
87
+ placeholder="Search layers..."
88
+ className="w-full bg-slate-950 border border-slate-700 rounded-lg pl-9 pr-8 py-2 text-xs text-slate-200 focus:outline-none focus:border-blue-500 transition-colors placeholder-slate-600"
89
+ value={searchQuery}
90
+ onChange={(e) => setSearchQuery(e.target.value)}
91
+ />
92
+ {searchQuery && (
93
+ <button
94
+ onClick={() => setSearchQuery('')}
95
+ className="absolute right-2 top-2 text-slate-500 hover:text-slate-300"
96
+ >
97
+ <X size={14} />
98
+ </button>
99
+ )}
100
+ </div>
101
  </div>
 
 
 
102
 
103
+ <div className="flex-1 overflow-y-auto p-4 space-y-6 scrollbar-thin scrollbar-thumb-slate-700 min-w-[16rem]">
104
+
105
+ {searchQuery ? (
106
+ // Search Results View
107
+ <div className="space-y-2">
108
+ <h3 className="text-xs font-semibold text-slate-500 uppercase tracking-widest mb-3">
109
+ Search Results ({filteredLayers.length})
110
+ </h3>
111
+ {filteredLayers.length > 0 ? (
112
+ filteredLayers.map(layer => (
113
+ <div
114
+ key={layer.type}
115
+ className="bg-slate-800 hover:bg-slate-750 p-3 rounded border border-slate-700 cursor-grab active:cursor-grabbing transition-colors group relative overflow-hidden"
116
+ onDragStart={(event) => onDragStart(event, layer.type)}
117
+ draggable
118
+ >
119
+ <div className="flex items-center gap-3 relative z-10">
120
+ <div className={`p-1.5 rounded transition-colors group-hover:bg-slate-900 bg-slate-900/50`}>
121
+ <Box size={14} className="text-slate-400 group-hover:text-blue-400" />
122
+ </div>
123
+ <div>
124
+ <div className="text-sm font-medium text-slate-200 group-hover:text-white">{layer.label}</div>
125
+ <div className="text-xs text-slate-500 leading-tight group-hover:text-slate-400 line-clamp-2">{layer.description}</div>
126
+ </div>
127
  </div>
128
  </div>
129
+ ))
130
+ ) : (
131
+ <div className="text-center text-slate-500 py-8 text-xs italic">
132
+ No layers found matching "{searchQuery}"
133
  </div>
134
+ )}
135
+ </div>
136
+ ) : (
137
+ // Categorized View
138
+ categories.map(category => (
139
+ <div key={category}>
140
+ <h3 className="text-xs font-semibold text-slate-500 uppercase tracking-widest mb-3 flex items-center gap-2">
141
+ {category}
142
+ <div className="h-px flex-1 bg-slate-800"></div>
143
+ </h3>
144
+ <div className="grid grid-cols-1 gap-2">
145
+ {Object.values(LAYER_DEFINITIONS)
146
+ .filter(l => l.category === category)
147
+ .map(layer => (
148
+ <div
149
+ key={layer.type}
150
+ className="bg-slate-800 hover:bg-slate-750 p-3 rounded border border-slate-700 cursor-grab active:cursor-grabbing transition-colors group relative overflow-hidden"
151
+ onDragStart={(event) => onDragStart(event, layer.type)}
152
+ draggable
153
+ >
154
+ <div className="flex items-center gap-3 relative z-10">
155
+ <div className={`p-1.5 rounded transition-colors group-hover:bg-slate-900 bg-slate-900/50`}>
156
+ <Box size={14} className="text-slate-400 group-hover:text-blue-400" />
157
+ </div>
158
+ <div>
159
+ <div className="text-sm font-medium text-slate-200 group-hover:text-white">{layer.label}</div>
160
+ <div className="text-xs text-slate-500 leading-tight group-hover:text-slate-400">{layer.description}</div>
161
+ </div>
 
 
 
 
162
  </div>
163
  </div>
164
+ ))}
165
+ </div>
166
  </div>
167
+ ))
168
+ )}
169
+ </div>
170
+
171
+ <div className="p-4 border-t border-slate-800 text-[10px] text-slate-500 text-center flex items-center justify-center gap-2 min-w-[16rem]">
172
+ <span>v1.2.0 Powered by Gemini 2.5</span>
173
+ <Circle size={8} className={isConnected ? "fill-emerald-500 text-emerald-500" : "fill-red-500 text-red-500"} />
174
+ </div>
175
  </div>
176
  </aside>
177
  );