umanggarg Claude Sonnet 4.6 commited on
Commit
85891ac
Β·
1 Parent(s): 22232b0

fix(ui): center view toggle + tone down accent for cool-dark base

Browse files

Header centering: replace fragile position:absolute with 3-column
grid-template-columns:1fr auto 1fr β€” the standard Linear/Vercel pattern
that guarantees true center regardless of asymmetric flanking content.
Restructure JSX to match: header-left | header-center | header-actions.

Accent tuning: saturated sienna reads as orange on cool-dark; shift to
muted terracotta (#C47B5A) and cut all opacity values by 30-50%.
Also reduce bloom gradients to barely-perceptible (Linear principle:
background texture should be felt, not seen). Dot grid switched to
neutral white dots β€” warm-tinted dots were tainting the cool base.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

Files changed (2) hide show
  1. ui/src/App.jsx +21 -15
  2. ui/src/index.css +60 -46
ui/src/App.jsx CHANGED
@@ -633,20 +633,21 @@ export default function App() {
633
 
634
  <div className="main">
635
  {/* Header */}
 
 
 
636
  <div className="chat-header">
637
- {/* Hamburger button β€” only visible on mobile */}
638
- <button
639
- className="mobile-menu-btn"
640
- onClick={() => setSidebarOpen(true)}
641
- aria-label="Open navigation"
642
- >
643
- <svg width="16" height="16" viewBox="0 0 16 16" fill="currentColor" aria-hidden="true">
644
- <path d="M1 2.75A.75.75 0 011.75 2h12.5a.75.75 0 010 1.5H1.75A.75.75 0 011 2.75zm0 5A.75.75 0 011.75 7h12.5a.75.75 0 010 1.5H1.75A.75.75 0 011 7.75zM1.75 12a.75.75 0 000 1.5h12.5a.75.75 0 000-1.5H1.75z"/>
645
- </svg>
646
- </button>
647
-
648
- <div style={{ display: "flex", alignItems: "center", gap: 8 }}>
649
- {/* Backend health dot */}
650
  {backendOk !== null && (
651
  <span
652
  className="backend-dot"
@@ -665,8 +666,9 @@ export default function App() {
665
  <span className="no-repo">All indexed repos</span>
666
  )}
667
  </div>
668
- <div className="header-actions">
669
- {/* View toggle: Chat ↔ Graph β€” only for specific repos, not "all" */}
 
670
  {activeRepo && activeRepo !== "all" && (
671
  <div className="view-toggle">
672
  <button
@@ -679,6 +681,10 @@ export default function App() {
679
  >Diagram <span style={{ fontSize: 8, verticalAlign: "middle", color: "var(--accent-soft)", marginLeft: 2 }}>●</span></button>
680
  </div>
681
  )}
 
 
 
 
682
  {view === "chat" && messages.length > 0 && (
683
  <button className="clear-btn" onClick={handleClear}>New Chat</button>
684
  )}
 
633
 
634
  <div className="main">
635
  {/* Header */}
636
+ {/* 3-column grid: left (repo badge) | center (toggle) | right (actions)
637
+ Equal 1fr flanks guarantee the center column is always truly centred,
638
+ regardless of asymmetric content on either side β€” the Linear/Vercel pattern. */}
639
  <div className="chat-header">
640
+ {/* LEFT β€” hamburger (mobile) + repo context */}
641
+ <div className="header-left">
642
+ <button
643
+ className="mobile-menu-btn"
644
+ onClick={() => setSidebarOpen(true)}
645
+ aria-label="Open navigation"
646
+ >
647
+ <svg width="16" height="16" viewBox="0 0 16 16" fill="currentColor" aria-hidden="true">
648
+ <path d="M1 2.75A.75.75 0 011.75 2h12.5a.75.75 0 010 1.5H1.75A.75.75 0 011 2.75zm0 5A.75.75 0 011.75 7h12.5a.75.75 0 010 1.5H1.75A.75.75 0 011 7.75zM1.75 12a.75.75 0 000 1.5h12.5a.75.75 0 000-1.5H1.75z"/>
649
+ </svg>
650
+ </button>
 
 
651
  {backendOk !== null && (
652
  <span
653
  className="backend-dot"
 
666
  <span className="no-repo">All indexed repos</span>
667
  )}
668
  </div>
669
+
670
+ {/* CENTER β€” view toggle, only when a specific repo is selected */}
671
+ <div className="header-center">
672
  {activeRepo && activeRepo !== "all" && (
673
  <div className="view-toggle">
674
  <button
 
681
  >Diagram <span style={{ fontSize: 8, verticalAlign: "middle", color: "var(--accent-soft)", marginLeft: 2 }}>●</span></button>
682
  </div>
683
  )}
684
+ </div>
685
+
686
+ {/* RIGHT β€” contextual actions */}
687
+ <div className="header-actions">
688
  {view === "chat" && messages.length > 0 && (
689
  <button className="clear-btn" onClick={handleClear}>New Chat</button>
690
  )}
ui/src/index.css CHANGED
@@ -68,16 +68,17 @@ html { height: 100dvh; background: #0E0F14; overflow: hidden; }
68
  --muted: #8A7A64; /* warm gray β€” file paths, secondary */
69
  --faint: #5E5044; /* dark sepia β€” timestamps, placeholders */
70
 
71
- /* Accent β€” burnt sienna, the classic illustration pigment.
72
- Every sketchbook artist has it. Warm, earthy, not digital-neon.
73
- More character than amber, less aggressive than orange. */
74
- --accent: #D4845A; /* burnt sienna β€” the ink */
75
- --accent-light: #E09A72; /* lighter on hover */
76
- --accent-soft: #EDBA9A; /* pale sienna text */
77
- --accent-lavender: #F2D0BC; /* high-luminance warm labels */
78
- --accent-dim: rgba(212, 132, 90, 0.14);
79
- --accent-glow: rgba(212, 132, 90, 0.26);
80
- --accent-border: rgba(212, 132, 90, 0.40);
 
81
 
82
  /* Secondary accent β€” warm teal, like watercolor over charcoal */
83
  --accent-2: #3A9E8C;
@@ -118,7 +119,7 @@ html { height: 100dvh; background: #0E0F14; overflow: hidden; }
118
  --shadow-sm: 0 1px 3px rgba(0,0,8,0.65), 0 1px 2px rgba(0,0,8,0.45);
119
  --shadow: 0 4px 16px rgba(0,0,8,0.75), 0 2px 8px rgba(0,0,8,0.55);
120
  --shadow-lg: 0 12px 40px rgba(0,0,8,0.85), 0 4px 16px rgba(0,0,8,0.65);
121
- --shadow-accent: 0 0 20px rgba(212, 132, 90, 0.25);
122
 
123
  /* Glass */
124
  --glass-bg: rgba(14, 15, 20, 0.82);
@@ -140,12 +141,13 @@ body {
140
  overflow: hidden;
141
  -webkit-font-smoothing: antialiased;
142
  -moz-osx-font-smoothing: grayscale;
143
- /* Atmospheric bloom β€” warm sienna punches harder against cool base.
144
- Increased opacity vs warm-bg version because cool contrast amplifies it. */
 
145
  background-image:
146
- radial-gradient(ellipse 70% 55% at -5% 0%, rgba(180, 80, 40, 0.40) 0%, transparent 65%),
147
- radial-gradient(ellipse 50% 40% at 105% 100%, rgba(160, 100, 60, 0.22) 0%, transparent 60%),
148
- radial-gradient(ellipse 80% 30% at 50% 50%, rgba(212, 132, 90, 0.06) 0%, transparent 70%);
149
  animation: page-in 0.35s cubic-bezier(0.16, 1, 0.3, 1) both;
150
  }
151
 
@@ -158,7 +160,7 @@ body::before {
158
  inset: 0;
159
  pointer-events: none;
160
  z-index: 0;
161
- background-image: radial-gradient(circle, rgba(212, 132, 90, 0.10) 1px, transparent 1px);
162
  background-size: 24px 24px;
163
  /* Vignette mask β€” grid strongest at center, invisible at edges */
164
  mask-image: radial-gradient(ellipse 75% 65% at 50% 50%, rgba(0,0,0,0.45) 0%, transparent 100%);
@@ -260,8 +262,8 @@ textarea:focus-visible {
260
  justify-content: center;
261
  color: #fff;
262
  box-shadow:
263
- 0 0 0 1px rgba(212, 132, 90, 0.4),
264
- 0 4px 16px rgba(212, 132, 90, 0.45);
265
  flex-shrink: 0;
266
  position: relative;
267
  overflow: hidden;
@@ -314,8 +316,8 @@ textarea:focus-visible {
314
  letter-spacing: 0.08em;
315
  color: var(--muted);
316
  margin-bottom: 6px;
317
- /* Subtle sienna tint so it reads as a warm structural element, not dead gray */
318
- background: linear-gradient(90deg, var(--muted) 0%, rgba(212,132,90,0.70) 100%);
319
  -webkit-background-clip: text;
320
  -webkit-text-fill-color: transparent;
321
  background-clip: text;
@@ -330,10 +332,10 @@ textarea:focus-visible {
330
  padding: 12px;
331
  position: relative;
332
  overflow: hidden;
333
- /* Sienna outer bloom + warm top-edge inner highlight */
334
  box-shadow:
335
- rgba(212, 132, 90, 0.14) 0px 8px 36px 0px,
336
- rgba(237, 228, 206, 0.08) 0px 1px 0px 0px inset;
337
  transition: border-color var(--transition), box-shadow var(--transition);
338
  }
339
  /* Sienna top-accent stripe β€” visual anchor for the primary action area */
@@ -344,7 +346,7 @@ textarea:focus-visible {
344
  left: 0;
345
  right: 0;
346
  height: 1px;
347
- background: linear-gradient(90deg, transparent 0%, rgba(212, 132, 90, 0.70) 40%, rgba(212, 132, 90, 0.70) 60%, transparent 100%);
348
  border-radius: 16px 16px 0 0;
349
  }
350
  .ingest-card:focus-within {
@@ -591,12 +593,17 @@ textarea:focus-visible {
591
 
592
  /* ── Chat header ──────────────────────────────────────────── */
593
  .chat-header {
594
- padding: 12px 24px;
595
- border-bottom: 1px solid rgba(237, 228, 206, 0.07);
596
- display: flex;
 
 
 
 
 
597
  align-items: center;
598
- gap: 12px;
599
- /* Frosted glass header β€” cool near-black with warm text overlay */
600
  background: rgba(10, 11, 16, 0.82);
601
  backdrop-filter: blur(16px) saturate(160%);
602
  -webkit-backdrop-filter: blur(16px) saturate(160%);
@@ -604,13 +611,24 @@ textarea:focus-visible {
604
  position: sticky;
605
  top: 0;
606
  z-index: 40;
607
- /* Inset top highlight creates glass-surface-catching-light effect */
608
  box-shadow:
609
- inset 0 1px 0 rgba(237, 228, 206, 0.08),
610
  0 1px 0 rgba(0, 0, 0, 0.4),
611
  0 4px 24px rgba(0, 0, 0, 0.30);
612
  }
613
 
 
 
 
 
 
 
 
 
 
 
 
 
614
  /* Bottom glow line on header */
615
  .chat-header::after {
616
  content: '';
@@ -619,12 +637,12 @@ textarea:focus-visible {
619
  left: 0;
620
  right: 0;
621
  height: 1px;
622
- background: linear-gradient(90deg, transparent, rgba(212,132,90,0.4), transparent);
623
  }
624
 
625
  .chat-header .repo-badge {
626
- background: rgba(212,132,90,0.12);
627
- border: 1px solid var(--accent-border);
628
  border-radius: var(--radius);
629
  color: var(--accent-soft);
630
  font-size: 12px;
@@ -1895,22 +1913,18 @@ textarea:focus-visible {
1895
  display: flex;
1896
  align-items: center;
1897
  gap: 10px;
 
1898
  }
1899
 
1900
  .view-toggle {
1901
  display: flex;
1902
- background: rgba(237,228,206,0.04);
1903
  border: 1px solid var(--border-strong);
1904
- /* Centered absolutely so it sits at the visual midpoint of the header
1905
- regardless of what's on the left (repo badge) or right (clear btn) */
1906
- position: absolute;
1907
- left: 50%;
1908
- transform: translateX(-50%);
1909
  border-radius: var(--radius-md);
1910
  overflow: hidden;
1911
  padding: 3px;
1912
  gap: 2px;
1913
- box-shadow: inset 0 1px 3px rgba(0,0,0,0.25);
1914
  }
1915
 
1916
  .view-btn {
@@ -1928,11 +1942,11 @@ textarea:focus-visible {
1928
  letter-spacing: -0.01em;
1929
  white-space: nowrap;
1930
  }
1931
- .view-btn:hover { background: rgba(237,228,206,0.08); color: var(--text); }
1932
  .view-btn.active {
1933
- background: var(--accent);
1934
- color: #fff;
1935
- box-shadow: 0 2px 10px rgba(212,132,90,0.45);
1936
  font-weight: 600;
1937
  }
1938
 
 
68
  --muted: #8A7A64; /* warm gray β€” file paths, secondary */
69
  --faint: #5E5044; /* dark sepia β€” timestamps, placeholders */
70
 
71
+ /* Accent β€” terracotta, brand identity color.
72
+ Slightly cooled/desaturated from pure sienna so it reads refined rather
73
+ than "orange" on the cool-dark base. Used sparingly: only active states
74
+ and primary CTAs. Background tints kept very low-opacity. */
75
+ --accent: #C47B5A; /* terracotta β€” slightly more red, less orange */
76
+ --accent-light: #D48F6E; /* lighter on hover */
77
+ --accent-soft: #DBA882; /* pale terracotta for secondary text */
78
+ --accent-lavender: #EDCAB0; /* high-luminance warm labels */
79
+ --accent-dim: rgba(196, 123, 90, 0.09); /* very subtle β€” backgrounds only */
80
+ --accent-glow: rgba(196, 123, 90, 0.18);
81
+ --accent-border: rgba(196, 123, 90, 0.32);
82
 
83
  /* Secondary accent β€” warm teal, like watercolor over charcoal */
84
  --accent-2: #3A9E8C;
 
119
  --shadow-sm: 0 1px 3px rgba(0,0,8,0.65), 0 1px 2px rgba(0,0,8,0.45);
120
  --shadow: 0 4px 16px rgba(0,0,8,0.75), 0 2px 8px rgba(0,0,8,0.55);
121
  --shadow-lg: 0 12px 40px rgba(0,0,8,0.85), 0 4px 16px rgba(0,0,8,0.65);
122
+ --shadow-accent: 0 0 20px rgba(196, 123, 90, 0.20);
123
 
124
  /* Glass */
125
  --glass-bg: rgba(14, 15, 20, 0.82);
 
141
  overflow: hidden;
142
  -webkit-font-smoothing: antialiased;
143
  -moz-osx-font-smoothing: grayscale;
144
+ /* Atmospheric bloom β€” subtle warmth at corners, barely perceptible.
145
+ Linear/Raycast principle: background texture is felt, not seen.
146
+ Heavy bloom was making the cool base look warm-muddy again. */
147
  background-image:
148
+ radial-gradient(ellipse 70% 55% at -5% 0%, rgba(180, 80, 40, 0.18) 0%, transparent 65%),
149
+ radial-gradient(ellipse 50% 40% at 105% 100%, rgba(160, 100, 60, 0.10) 0%, transparent 60%),
150
+ radial-gradient(ellipse 80% 30% at 50% 50%, rgba(212, 132, 90, 0.03) 0%, transparent 70%);
151
  animation: page-in 0.35s cubic-bezier(0.16, 1, 0.3, 1) both;
152
  }
153
 
 
160
  inset: 0;
161
  pointer-events: none;
162
  z-index: 0;
163
+ background-image: radial-gradient(circle, rgba(255, 255, 255, 0.07) 1px, transparent 1px);
164
  background-size: 24px 24px;
165
  /* Vignette mask β€” grid strongest at center, invisible at edges */
166
  mask-image: radial-gradient(ellipse 75% 65% at 50% 50%, rgba(0,0,0,0.45) 0%, transparent 100%);
 
262
  justify-content: center;
263
  color: #fff;
264
  box-shadow:
265
+ 0 0 0 1px rgba(196, 123, 90, 0.28),
266
+ 0 4px 16px rgba(196, 123, 90, 0.22);
267
  flex-shrink: 0;
268
  position: relative;
269
  overflow: hidden;
 
316
  letter-spacing: 0.08em;
317
  color: var(--muted);
318
  margin-bottom: 6px;
319
+ /* Subtle warm tint β€” makes section headers feel structural, not dead */
320
+ background: linear-gradient(90deg, var(--muted) 0%, rgba(196,123,90,0.50) 100%);
321
  -webkit-background-clip: text;
322
  -webkit-text-fill-color: transparent;
323
  background-clip: text;
 
332
  padding: 12px;
333
  position: relative;
334
  overflow: hidden;
335
+ /* Subtle depth: very faint warm bloom + top-edge inner highlight */
336
  box-shadow:
337
+ rgba(196, 123, 90, 0.08) 0px 8px 36px 0px,
338
+ rgba(255, 255, 255, 0.06) 0px 1px 0px 0px inset;
339
  transition: border-color var(--transition), box-shadow var(--transition);
340
  }
341
  /* Sienna top-accent stripe β€” visual anchor for the primary action area */
 
346
  left: 0;
347
  right: 0;
348
  height: 1px;
349
+ background: linear-gradient(90deg, transparent 0%, rgba(196, 123, 90, 0.45) 40%, rgba(196, 123, 90, 0.45) 60%, transparent 100%);
350
  border-radius: 16px 16px 0 0;
351
  }
352
  .ingest-card:focus-within {
 
593
 
594
  /* ── Chat header ──────────────────────────────────────────── */
595
  .chat-header {
596
+ padding: 0 24px;
597
+ border-bottom: 1px solid rgba(255, 255, 255, 0.07);
598
+ /* 3-column grid: equal 1fr flanks + auto centre.
599
+ The centre column only takes as much width as its content, and the two
600
+ equal 1fr sides consume the rest β€” so the toggle is always pixel-perfect
601
+ centred regardless of what's on either flank. */
602
+ display: grid;
603
+ grid-template-columns: 1fr auto 1fr;
604
  align-items: center;
605
+ gap: 0;
606
+ /* Frosted glass header */
607
  background: rgba(10, 11, 16, 0.82);
608
  backdrop-filter: blur(16px) saturate(160%);
609
  -webkit-backdrop-filter: blur(16px) saturate(160%);
 
611
  position: sticky;
612
  top: 0;
613
  z-index: 40;
 
614
  box-shadow:
615
+ inset 0 1px 0 rgba(255, 255, 255, 0.06),
616
  0 1px 0 rgba(0, 0, 0, 0.4),
617
  0 4px 24px rgba(0, 0, 0, 0.30);
618
  }
619
 
620
+ .header-left {
621
+ display: flex;
622
+ align-items: center;
623
+ gap: 8px;
624
+ }
625
+
626
+ .header-center {
627
+ display: flex;
628
+ justify-content: center;
629
+ align-items: center;
630
+ }
631
+
632
  /* Bottom glow line on header */
633
  .chat-header::after {
634
  content: '';
 
637
  left: 0;
638
  right: 0;
639
  height: 1px;
640
+ background: linear-gradient(90deg, transparent, rgba(196,123,90,0.20), transparent);
641
  }
642
 
643
  .chat-header .repo-badge {
644
+ background: rgba(255,255,255,0.05);
645
+ border: 1px solid var(--border-strong);
646
  border-radius: var(--radius);
647
  color: var(--accent-soft);
648
  font-size: 12px;
 
1913
  display: flex;
1914
  align-items: center;
1915
  gap: 10px;
1916
+ justify-content: flex-end;
1917
  }
1918
 
1919
  .view-toggle {
1920
  display: flex;
1921
+ background: rgba(255,255,255,0.04);
1922
  border: 1px solid var(--border-strong);
 
 
 
 
 
1923
  border-radius: var(--radius-md);
1924
  overflow: hidden;
1925
  padding: 3px;
1926
  gap: 2px;
1927
+ box-shadow: inset 0 1px 3px rgba(0,0,0,0.30);
1928
  }
1929
 
1930
  .view-btn {
 
1942
  letter-spacing: -0.01em;
1943
  white-space: nowrap;
1944
  }
1945
+ .view-btn:hover { background: rgba(255,255,255,0.06); color: var(--text); }
1946
  .view-btn.active {
1947
+ background: rgba(255,255,255,0.10);
1948
+ color: var(--text);
1949
+ box-shadow: inset 0 1px 0 rgba(255,255,255,0.12);
1950
  font-weight: 600;
1951
  }
1952