NeonRyan Claude Opus 4.7 (1M context) commited on
Commit
00f7e20
·
unverified ·
1 Parent(s): 98d3405

UI: sidebar redesign + chat header signout cleanup (#56)

Browse files

- Sidebar: swap chevron toggle for PanelLeft, swap Plus for SquarePen on collapsed-state new-chat button.
- Sidebar: move "New Chat" out of the main column to an icon button next to search.
- Sidebar: restyle canvas button as a gradient pill with hover shimmer.
- Sidebar: tighten toggle/menu button sizing (32x32) for visual consistency.
- ChatPage header: remove the standalone sign-out button; sign-out lives in the sidebar user menu.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

phd-advisor-frontend/src/App.js CHANGED
@@ -89,7 +89,7 @@ function App() {
89
  />
90
  )}
91
  {currentView === 'chat' && isAuthenticated && (
92
- <ChatPage
93
  user={user}
94
  authToken={authToken}
95
  onNavigateToHome={navigateToHome}
 
89
  />
90
  )}
91
  {currentView === 'chat' && isAuthenticated && (
92
+ <ChatPage
93
  user={user}
94
  authToken={authToken}
95
  onNavigateToHome={navigateToHome}
phd-advisor-frontend/src/components/Sidebar.js CHANGED
@@ -1,16 +1,16 @@
1
  import React, { useState, useEffect } from 'react';
2
- import {
3
- MessageSquare,
4
- Plus,
5
- Search,
6
- MoreVertical,
7
- Trash2,
 
8
  Edit3,
9
  LogOut,
10
  User,
11
  Settings,
12
- ChevronLeft,
13
- ChevronRight,
14
  FileText
15
  } from 'lucide-react';
16
  import { useAppConfig } from '../contexts/AppConfigContext';
@@ -201,7 +201,7 @@ const Sidebar = ({
201
  onClick={toggleSidebar}
202
  title="Collapse sidebar"
203
  >
204
- <ChevronLeft size={16} />
205
  </button>
206
 
207
  <div className="user-menu-container">
@@ -228,21 +228,12 @@ const Sidebar = ({
228
  </div>
229
  </div>
230
 
231
- <button
232
- className="new-chat-button"
233
- onClick={handleNewChat}
234
- disabled={isCreatingNewChat}
235
- >
236
- <Plus size={16} />
237
- <span>{isCreatingNewChat ? 'Creating...' : 'New Chat'}</span>
238
- </button>
239
-
240
- <button
241
  className="sidebar-canvas-btn"
242
  onClick={onNavigateToCanvas}
243
  title={canvasLabel}
244
  >
245
- <FileText size={20} />
246
  {!isCollapsed && <span>{canvasLabel}</span>}
247
  </button>
248
  </>
@@ -256,15 +247,15 @@ const Sidebar = ({
256
  onClick={toggleSidebar}
257
  title="Expand sidebar"
258
  >
259
- <ChevronRight size={20} />
260
  </button>
261
- <button
262
- className="collapsed-new-chat"
263
- onClick={handleNewChat}
264
  title="New Chat"
265
  disabled={isCreatingNewChat}
266
  >
267
- <Plus size={20} />
268
  </button>
269
  <button
270
  className="sidebar-canvas-btn"
@@ -278,7 +269,7 @@ const Sidebar = ({
278
  )}
279
  </div>
280
 
281
- {/* Search - only show when expanded */}
282
  {!isCollapsed && (
283
  <div className="sidebar-search">
284
  <div className="search-container">
@@ -291,6 +282,14 @@ const Sidebar = ({
291
  className="search-input"
292
  />
293
  </div>
 
 
 
 
 
 
 
 
294
  </div>
295
  )}
296
 
 
1
  import React, { useState, useEffect } from 'react';
2
+ import {
3
+ MessageSquare,
4
+ Plus,
5
+ SquarePen,
6
+ Search,
7
+ MoreVertical,
8
+ Trash2,
9
  Edit3,
10
  LogOut,
11
  User,
12
  Settings,
13
+ PanelLeft,
 
14
  FileText
15
  } from 'lucide-react';
16
  import { useAppConfig } from '../contexts/AppConfigContext';
 
201
  onClick={toggleSidebar}
202
  title="Collapse sidebar"
203
  >
204
+ <PanelLeft size={18} />
205
  </button>
206
 
207
  <div className="user-menu-container">
 
228
  </div>
229
  </div>
230
 
231
+ <button
 
 
 
 
 
 
 
 
 
232
  className="sidebar-canvas-btn"
233
  onClick={onNavigateToCanvas}
234
  title={canvasLabel}
235
  >
236
+ <FileText size={18} />
237
  {!isCollapsed && <span>{canvasLabel}</span>}
238
  </button>
239
  </>
 
247
  onClick={toggleSidebar}
248
  title="Expand sidebar"
249
  >
250
+ <PanelLeft size={20} />
251
  </button>
252
+ <button
253
+ className="collapsed-new-chat"
254
+ onClick={handleNewChat}
255
  title="New Chat"
256
  disabled={isCreatingNewChat}
257
  >
258
+ <SquarePen size={20} />
259
  </button>
260
  <button
261
  className="sidebar-canvas-btn"
 
269
  )}
270
  </div>
271
 
272
+ {/* Search + New Chat - only show when expanded */}
273
  {!isCollapsed && (
274
  <div className="sidebar-search">
275
  <div className="search-container">
 
282
  className="search-input"
283
  />
284
  </div>
285
+ <button
286
+ className="new-chat-icon-btn"
287
+ onClick={handleNewChat}
288
+ disabled={isCreatingNewChat}
289
+ title={isCreatingNewChat ? 'Creating...' : 'New Chat'}
290
+ >
291
+ <SquarePen size={18} />
292
+ </button>
293
  </div>
294
  )}
295
 
phd-advisor-frontend/src/pages/ChatPage.js CHANGED
@@ -1,5 +1,5 @@
1
  import React, { useState, useEffect, useRef, useMemo } from 'react';
2
- import { Home, MessageCircle, Reply, X, Sparkles, Users, Settings2, FileText , LogOut, Menu} from 'lucide-react';
3
  import EnhancedChatInput from '../components/EnhancedChatInput';
4
  import MessageBubble from '../components/MessageBubble';
5
  import ThinkingIndicator from '../components/ThinkingIndicator';
@@ -808,29 +808,20 @@ const handleNewChat = async (sessionId = null) => {
808
  </div>
809
  )}
810
 
811
- {/* Optional: Add header sign out button */}
812
- <button
813
- className="header-signout-btn"
814
- onClick={onSignOut}
815
- title="Sign Out"
816
- >
817
- <LogOut size={16} />
818
- </button>
819
-
820
  {/* Export Button */}
821
- <ExportButton
822
- hasMessages={hasConversationMessages}
823
  currentSessionId={currentSessionId}
824
  authToken={authToken}
825
  />
826
-
827
  {/* Provider Dropdown */}
828
- <ProviderDropdown
829
  currentProvider={currentProvider}
830
  onProviderChange={handleProviderSwitch}
831
  isLoading={isProviderSwitching}
832
  />
833
-
834
  {/* Theme Toggle */}
835
  <ThemeToggle />
836
  </div>
 
1
  import React, { useState, useEffect, useRef, useMemo } from 'react';
2
+ import { Home, MessageCircle, Reply, X, Sparkles, Users, Settings2, FileText, Menu } from 'lucide-react';
3
  import EnhancedChatInput from '../components/EnhancedChatInput';
4
  import MessageBubble from '../components/MessageBubble';
5
  import ThinkingIndicator from '../components/ThinkingIndicator';
 
808
  </div>
809
  )}
810
 
 
 
 
 
 
 
 
 
 
811
  {/* Export Button */}
812
+ <ExportButton
813
+ hasMessages={hasConversationMessages}
814
  currentSessionId={currentSessionId}
815
  authToken={authToken}
816
  />
817
+
818
  {/* Provider Dropdown */}
819
+ <ProviderDropdown
820
  currentProvider={currentProvider}
821
  onProviderChange={handleProviderSwitch}
822
  isLoading={isProviderSwitching}
823
  />
824
+
825
  {/* Theme Toggle */}
826
  <ThemeToggle />
827
  </div>
phd-advisor-frontend/src/styles/Sidebar.css CHANGED
@@ -27,16 +27,18 @@
27
 
28
  /* Toggle Button - Matches User Menu Style */
29
  .sidebar-toggle {
30
- padding: 6px;
 
 
 
 
 
31
  border: none;
32
  background: none;
33
  border-radius: 6px;
34
  cursor: pointer;
35
  color: var(--text-secondary, #6b7280);
36
  transition: all 0.2s ease;
37
- display: flex;
38
- align-items: center;
39
- justify-content: center;
40
  }
41
 
42
  .sidebar-toggle:hover {
@@ -188,7 +190,12 @@
188
  }
189
 
190
  .user-menu-button {
191
- padding: 6px;
 
 
 
 
 
192
  border: none;
193
  background: none;
194
  border-radius: 6px;
@@ -289,12 +296,45 @@
289
 
290
  /* Search Section */
291
  .sidebar-search {
 
 
 
292
  padding: 16px 20px;
293
  border-bottom: 1px solid var(--border-light, #e5e7eb);
294
  flex-shrink: 0;
295
  transition: all 0.3s ease;
296
  }
297
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
298
  .dark .sidebar-search {
299
  border-bottom-color: var(--border-dark, #374151);
300
  }
@@ -704,26 +744,83 @@
704
  }
705
 
706
  .sidebar-canvas-btn {
 
 
707
  display: flex;
708
  align-items: center;
709
- gap: 12px;
 
710
  width: 100%;
711
- padding: 12px 16px;
712
- background: var(--feature-bg);
713
- border: 1px solid var(--accent-primary);
714
- border-radius: 8px;
715
- color: var(--accent-primary);
716
  cursor: pointer;
717
- transition: all 0.2s ease;
718
- margin-bottom: 8px;
719
  font-size: 14px;
720
- font-weight: 500;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
721
  }
722
 
723
  .sidebar-canvas-btn:hover {
724
- background: var(--accent-primary);
725
- color: white;
726
- transform: translateY(-1px);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
727
  }
728
 
729
  .sidebar.collapsed .sidebar-canvas-btn span {
 
27
 
28
  /* Toggle Button - Matches User Menu Style */
29
  .sidebar-toggle {
30
+ display: flex;
31
+ align-items: center;
32
+ justify-content: center;
33
+ width: 32px;
34
+ height: 32px;
35
+ padding: 0;
36
  border: none;
37
  background: none;
38
  border-radius: 6px;
39
  cursor: pointer;
40
  color: var(--text-secondary, #6b7280);
41
  transition: all 0.2s ease;
 
 
 
42
  }
43
 
44
  .sidebar-toggle:hover {
 
190
  }
191
 
192
  .user-menu-button {
193
+ display: flex;
194
+ align-items: center;
195
+ justify-content: center;
196
+ width: 32px;
197
+ height: 32px;
198
+ padding: 0;
199
  border: none;
200
  background: none;
201
  border-radius: 6px;
 
296
 
297
  /* Search Section */
298
  .sidebar-search {
299
+ display: flex;
300
+ align-items: center;
301
+ gap: 8px;
302
  padding: 16px 20px;
303
  border-bottom: 1px solid var(--border-light, #e5e7eb);
304
  flex-shrink: 0;
305
  transition: all 0.3s ease;
306
  }
307
 
308
+ .sidebar-search .search-container {
309
+ flex: 1;
310
+ }
311
+
312
+ .new-chat-icon-btn {
313
+ display: flex;
314
+ align-items: center;
315
+ justify-content: center;
316
+ width: 36px;
317
+ height: 36px;
318
+ flex-shrink: 0;
319
+ border: none;
320
+ border-radius: 8px;
321
+ background: #2663EB;
322
+ color: #fff;
323
+ cursor: pointer;
324
+ transition: background 0.15s ease, transform 0.15s ease;
325
+ }
326
+
327
+ .new-chat-icon-btn:hover {
328
+ background: #1d4fc4;
329
+ transform: translateY(-1px);
330
+ }
331
+
332
+ .new-chat-icon-btn:disabled {
333
+ opacity: 0.5;
334
+ cursor: not-allowed;
335
+ transform: none;
336
+ }
337
+
338
  .dark .sidebar-search {
339
  border-bottom-color: var(--border-dark, #374151);
340
  }
 
744
  }
745
 
746
  .sidebar-canvas-btn {
747
+ position: relative;
748
+ overflow: hidden;
749
  display: flex;
750
  align-items: center;
751
+ justify-content: center;
752
+ gap: 10px;
753
  width: 100%;
754
+ padding: 13px 20px;
755
+ background: linear-gradient(180deg, #7B7BF0 0%, #5957E8 100%);
756
+ border: 1px solid rgba(255, 255, 255, 0.14);
757
+ border-radius: 999px;
758
+ color: #ffffff;
759
  cursor: pointer;
 
 
760
  font-size: 14px;
761
+ font-weight: 700;
762
+ letter-spacing: -0.005em;
763
+ margin-top: 14px;
764
+ margin-bottom: 8px;
765
+ box-shadow:
766
+ 0 0 32px -10px rgba(99, 102, 241, 0.45),
767
+ 0 4px 14px -4px rgba(89, 87, 232, 0.45),
768
+ inset 0 1px 0 rgba(255, 255, 255, 0.18);
769
+ transition:
770
+ transform 0.25s cubic-bezier(0.4, 0, 0.2, 1),
771
+ box-shadow 0.3s cubic-bezier(0.4, 0, 0.2, 1),
772
+ background 0.25s ease;
773
+ }
774
+
775
+ /* Sliding shimmer that sweeps across on hover */
776
+ .sidebar-canvas-btn::before {
777
+ content: '';
778
+ position: absolute;
779
+ top: 0;
780
+ left: -100%;
781
+ width: 100%;
782
+ height: 100%;
783
+ background: linear-gradient(
784
+ 90deg,
785
+ transparent 0%,
786
+ rgba(255, 255, 255, 0.25) 50%,
787
+ transparent 100%
788
+ );
789
+ transition: left 0.6s ease;
790
+ pointer-events: none;
791
+ }
792
+
793
+ .sidebar-canvas-btn > * {
794
+ position: relative;
795
+ z-index: 1;
796
+ }
797
+
798
+ .sidebar-canvas-btn svg {
799
+ color: #ffffff;
800
+ flex-shrink: 0;
801
+ transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);
802
  }
803
 
804
  .sidebar-canvas-btn:hover {
805
+ transform: translateY(-2px) scale(1.015);
806
+ background: linear-gradient(180deg, #8C8CF7 0%, #6663EE 100%);
807
+ box-shadow:
808
+ 0 0 80px -8px rgba(124, 124, 240, 0.85),
809
+ 0 12px 28px -6px rgba(89, 87, 232, 0.7),
810
+ inset 0 1px 0 rgba(255, 255, 255, 0.32);
811
+ }
812
+
813
+ .sidebar-canvas-btn:hover::before {
814
+ left: 100%;
815
+ }
816
+
817
+ .sidebar-canvas-btn:hover svg {
818
+ transform: rotate(-8deg) scale(1.1);
819
+ }
820
+
821
+ .sidebar-canvas-btn:active {
822
+ transform: translateY(0) scale(1);
823
+ transition-duration: 0.1s;
824
  }
825
 
826
  .sidebar.collapsed .sidebar-canvas-btn span {