umanggarg Claude Sonnet 4.6 commited on
Commit
48b0262
Β·
1 Parent(s): 1b5234a

design(ui): Awwwards-quality typography, SVG icons, lit-edge diagram tabs

Browse files

Landing hero:
- Compass 64β†’88px β€” scales with viewport without looking lost
- Headline 34β†’48px Anthropic Serif β€” makes it a moment, not a label
- "any" wrapped in gradient em β€” warm sienna accent highlights the key promise
- Onboarding step p: var(--muted)β†’var(--text-2) β€” body text on a learning tool
must be readable, not decorative

Diagram mode tabs:
- Unicode β—ˆβ¬‘β—« replaced with inline SVG TabIcon component β€” infinitely crisp at
every DPI; unicode glyphs rasterise at screen resolution and look fuzzy at 2Γ—
- "Lit edge" ::before gradient top-line on active card β€” the same depth signal
used by Linear, Vercel, Raycast; materialises light catching a raised edge
- Padding 8px 14px β†’ 11px 18px, min-width 130β†’150px β€” feature cards not form controls
- Icon color transitions on hover/active β€” guides the eye to the selection
- diagram-type-desc: var(--muted)β†’var(--text-2) β€” readable context

Chat suggest state:
- h2: 22β†’28px β€” repo selected is an invitation, needs presence

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

ui/src/App.jsx CHANGED
@@ -728,7 +728,7 @@ export default function App() {
728
  // No repo selected yet (landing), or All repos selected but nothing indexed
729
  <div className="onboarding-steps">
730
  <div className="onboarding-header">
731
- <svg width="64" height="64" viewBox="0 0 24 24" fill="none" style={{ marginBottom: 16 }}>
732
  {/* N β€” pulses bright */}
733
  <path className="compass-north" d="M12 2 L14.5 7 L12 12 L9.5 7 Z" fill="var(--accent)"/>
734
  {/* S β€” delayed fade */}
@@ -740,7 +740,7 @@ export default function App() {
740
  {/* Center */}
741
  <circle cx="12" cy="12" r="1.4" fill="var(--accent)"/>
742
  </svg>
743
- <div className="onboarding-headline">Map any codebase</div>
744
  <div className="onboarding-sub">Index any public repo and ask questions about the code β€” architecture, data flow, classes, functions, and more.</div>
745
  </div>
746
  <div className="onboarding-step active">
 
728
  // No repo selected yet (landing), or All repos selected but nothing indexed
729
  <div className="onboarding-steps">
730
  <div className="onboarding-header">
731
+ <svg width="88" height="88" viewBox="0 0 24 24" fill="none" style={{ marginBottom: 20 }}>
732
  {/* N β€” pulses bright */}
733
  <path className="compass-north" d="M12 2 L14.5 7 L12 12 L9.5 7 Z" fill="var(--accent)"/>
734
  {/* S β€” delayed fade */}
 
740
  {/* Center */}
741
  <circle cx="12" cy="12" r="1.4" fill="var(--accent)"/>
742
  </svg>
743
+ <div className="onboarding-headline">Map <em>any</em> codebase</div>
744
  <div className="onboarding-sub">Index any public repo and ask questions about the code β€” architecture, data flow, classes, functions, and more.</div>
745
  </div>
746
  <div className="onboarding-step active">
ui/src/components/DiagramView.jsx CHANGED
@@ -22,7 +22,7 @@ import NodeDetailPanel from "./NodeDetailPanel";
22
 
23
  // ── Diagram tab definitions ───────────────────────────────────────────────────
24
  const EXPLORE_TAB = {
25
- id: "explore", label: "Explore", desc: "Guided concept tour", icon: "β—ˆ",
26
  };
27
 
28
  // Only AST-verified diagrams β€” Sequence and Data Flow were removed because
@@ -33,16 +33,54 @@ const DIAGRAM_TABS = [
33
  id: "architecture",
34
  label: "Architecture",
35
  desc: "Components & connections",
36
- icon: "⬑",
37
  },
38
  {
39
  id: "class",
40
  label: "Class Hierarchy",
41
  desc: "Classes & relationships",
42
- icon: "β—«",
43
  },
44
  ];
45
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
46
  const ALL_TABS = [EXPLORE_TAB, ...DIAGRAM_TABS];
47
 
48
  export default function DiagramView({ repo, onAskAbout, focusFiles }) {
@@ -246,7 +284,7 @@ export default function DiagramView({ repo, onAskAbout, focusFiles }) {
246
  : "rgba(212,132,90,0.25)",
247
  }}
248
  >
249
- <span className="diagram-type-icon" style={{ color: "var(--accent-soft)" }}>β—ˆ</span>
250
  <span className="diagram-type-label" style={{ color: diagramType === "explore" ? "var(--accent)" : "var(--accent-soft)" }}>Explore</span>
251
  <span className="diagram-type-desc">Guided concept tour</span>
252
  </button>
@@ -265,7 +303,7 @@ export default function DiagramView({ repo, onAskAbout, focusFiles }) {
265
  className={`diagram-type-btn${diagramType === t.id ? " active" : ""}`}
266
  onClick={() => setType(t.id)}
267
  >
268
- <span className="diagram-type-icon">{t.icon}</span>
269
  <span className="diagram-type-label">{t.label}</span>
270
  <span className="diagram-type-desc">{t.desc}</span>
271
  </button>
 
22
 
23
  // ── Diagram tab definitions ───────────────────────────────────────────────────
24
  const EXPLORE_TAB = {
25
+ id: "explore", label: "Explore", desc: "Guided concept tour",
26
  };
27
 
28
  // Only AST-verified diagrams β€” Sequence and Data Flow were removed because
 
33
  id: "architecture",
34
  label: "Architecture",
35
  desc: "Components & connections",
 
36
  },
37
  {
38
  id: "class",
39
  label: "Class Hierarchy",
40
  desc: "Classes & relationships",
 
41
  },
42
  ];
43
 
44
+ // ── Tab icons (SVG) ───────────────────────────────────────────────────────────
45
+ // Inline SVGs render crisp at every DPI β€” unicode glyphs (β—ˆ ⬑ β—«) are
46
+ // rasterised at screen resolution and look blurry on high-DPI displays.
47
+ function TabIcon({ id }) {
48
+ if (id === "explore") return (
49
+ <svg width="16" height="16" viewBox="0 0 24 24" fill="none" aria-hidden="true">
50
+ {/* Compass rose β€” N point pulses in the landing animation */}
51
+ <path d="M12 2L14.5 7.5L12 12L9.5 7.5Z" fill="currentColor"/>
52
+ <path d="M12 22L13.5 16.5L12 12L10.5 16.5Z" fill="currentColor" opacity="0.45"/>
53
+ <path d="M22 12L16.5 10.5L12 12L16.5 13.5Z" fill="currentColor" opacity="0.45"/>
54
+ <path d="M2 12L7.5 10.5L12 12L7.5 13.5Z" fill="currentColor" opacity="0.45"/>
55
+ <circle cx="12" cy="12" r="1.5" fill="currentColor"/>
56
+ </svg>
57
+ );
58
+ if (id === "architecture") return (
59
+ <svg width="16" height="16" viewBox="0 0 24 24" fill="none"
60
+ stroke="currentColor" strokeWidth="1.75" strokeLinecap="round" aria-hidden="true">
61
+ {/* Three nodes connected by edges β€” represents a dependency/import graph */}
62
+ <circle cx="5" cy="12" r="2.5"/>
63
+ <circle cx="19" cy="6.5" r="2.5"/>
64
+ <circle cx="19" cy="17.5" r="2.5"/>
65
+ <line x1="7.4" y1="11" x2="16.6" y2="7.5"/>
66
+ <line x1="7.4" y1="13" x2="16.6" y2="16.5"/>
67
+ </svg>
68
+ );
69
+ if (id === "class") return (
70
+ <svg width="16" height="16" viewBox="0 0 24 24" fill="none"
71
+ stroke="currentColor" strokeWidth="1.75" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
72
+ {/* Parent node + two children β€” represents inheritance / class tree */}
73
+ <rect x="8.5" y="2" width="7" height="5" rx="1.5"/>
74
+ <rect x="1" y="17" width="7" height="5" rx="1.5"/>
75
+ <rect x="16" y="17" width="7" height="5" rx="1.5"/>
76
+ <line x1="12" y1="7" x2="12" y2="12"/>
77
+ <line x1="12" y1="12" x2="4.5" y2="17"/>
78
+ <line x1="12" y1="12" x2="19.5" y2="17"/>
79
+ </svg>
80
+ );
81
+ return null;
82
+ }
83
+
84
  const ALL_TABS = [EXPLORE_TAB, ...DIAGRAM_TABS];
85
 
86
  export default function DiagramView({ repo, onAskAbout, focusFiles }) {
 
284
  : "rgba(212,132,90,0.25)",
285
  }}
286
  >
287
+ <span className="diagram-type-icon" style={{ color: "var(--accent-soft)" }}><TabIcon id="explore" /></span>
288
  <span className="diagram-type-label" style={{ color: diagramType === "explore" ? "var(--accent)" : "var(--accent-soft)" }}>Explore</span>
289
  <span className="diagram-type-desc">Guided concept tour</span>
290
  </button>
 
303
  className={`diagram-type-btn${diagramType === t.id ? " active" : ""}`}
304
  onClick={() => setType(t.id)}
305
  >
306
+ <span className="diagram-type-icon"><TabIcon id={t.id} /></span>
307
  <span className="diagram-type-label">{t.label}</span>
308
  <span className="diagram-type-desc">{t.desc}</span>
309
  </button>
ui/src/index.css CHANGED
@@ -1319,15 +1319,26 @@ textarea:focus-visible {
1319
  }
1320
 
1321
  .onboarding-headline {
1322
- font-size: 34px;
 
1323
  font-weight: 400;
1324
  font-family: "Anthropic Serif", Georgia, serif;
1325
- letter-spacing: -0.02em;
1326
- line-height: 1.1;
1327
- margin-bottom: 12px;
1328
  color: var(--text);
1329
  }
1330
 
 
 
 
 
 
 
 
 
 
 
1331
  .onboarding-sub {
1332
  font-size: 15px;
1333
  color: var(--text-2);
@@ -1422,7 +1433,8 @@ textarea:focus-visible {
1422
  }
1423
  .onboarding-step p {
1424
  font-size: 13px;
1425
- color: var(--muted);
 
1426
  margin: 3px 0;
1427
  line-height: 1.55;
1428
  }
@@ -1441,7 +1453,8 @@ textarea:focus-visible {
1441
  /* Suggest state */
1442
  .suggest-state { max-width: 540px; width: 100%; text-align: center; }
1443
  .suggest-state h2 {
1444
- font-size: 22px;
 
1445
  font-weight: 400;
1446
  font-family: "Anthropic Serif", Georgia, serif;
1447
  letter-spacing: -0.02em;
@@ -2121,50 +2134,80 @@ textarea:focus-visible {
2121
  .diagram-type-bar {
2122
  display: flex;
2123
  gap: 8px;
2124
- padding: 12px 24px;
2125
  border-bottom: 1px solid var(--border-subtle);
2126
  flex-shrink: 0;
2127
- background: rgba(20, 18, 14, 0.55);
2128
  }
2129
 
2130
  .diagram-type-btn {
2131
  display: flex;
2132
  flex-direction: column;
2133
  align-items: flex-start;
2134
- gap: 2px;
2135
- padding: 8px 14px;
2136
- border-radius: 8px;
 
2137
  border: 1px solid var(--border);
2138
  background: transparent;
2139
  cursor: pointer;
2140
- transition: background var(--transition), border-color var(--transition);
2141
- min-width: 130px;
 
 
 
2142
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2143
  .diagram-type-btn:hover {
2144
  background: rgba(237,228,206,0.04);
2145
  border-color: var(--accent-border);
2146
  }
2147
  .diagram-type-btn.active {
2148
- background: rgba(212,132,90,0.15);
2149
- border-color: rgba(212,132,90,0.5);
 
2150
  }
 
2151
 
2152
  .diagram-type-icon {
2153
- font-size: 16px;
2154
- line-height: 1;
2155
- margin-bottom: 2px;
 
 
 
2156
  }
 
 
 
2157
  .diagram-type-label {
2158
- font-size: 12px;
2159
  font-weight: 600;
2160
  color: var(--text);
2161
  font-family: var(--mono);
 
2162
  }
2163
  .diagram-type-btn.active .diagram-type-label { color: var(--accent); }
2164
 
 
2165
  .diagram-type-desc {
2166
- font-size: 10px;
2167
- color: var(--muted);
 
2168
  }
2169
 
2170
  /* ── Canvas ── */
 
1319
  }
1320
 
1321
  .onboarding-headline {
1322
+ /* 48px makes this a moment, not a label β€” the first thing that lands */
1323
+ font-size: 48px;
1324
  font-weight: 400;
1325
  font-family: "Anthropic Serif", Georgia, serif;
1326
+ letter-spacing: -0.03em;
1327
+ line-height: 1.05;
1328
+ margin-bottom: 14px;
1329
  color: var(--text);
1330
  }
1331
 
1332
+ /* "any" in "Map any codebase" β€” gradient accent highlights the key idea:
1333
+ that Cartographer works on every repo, not just pre-selected ones */
1334
+ .onboarding-headline em {
1335
+ font-style: normal;
1336
+ background: linear-gradient(110deg, var(--accent-soft) 0%, var(--accent) 65%);
1337
+ -webkit-background-clip: text;
1338
+ -webkit-text-fill-color: transparent;
1339
+ background-clip: text;
1340
+ }
1341
+
1342
  .onboarding-sub {
1343
  font-size: 15px;
1344
  color: var(--text-2);
 
1433
  }
1434
  .onboarding-step p {
1435
  font-size: 13px;
1436
+ /* text-2 not muted β€” this is the body of a learning step, not decoration */
1437
+ color: var(--text-2);
1438
  margin: 3px 0;
1439
  line-height: 1.55;
1440
  }
 
1453
  /* Suggest state */
1454
  .suggest-state { max-width: 540px; width: 100%; text-align: center; }
1455
  .suggest-state h2 {
1456
+ /* 28px gives this moment presence β€” you've chosen a repo, this is the invitation */
1457
+ font-size: 28px;
1458
  font-weight: 400;
1459
  font-family: "Anthropic Serif", Georgia, serif;
1460
  letter-spacing: -0.02em;
 
2134
  .diagram-type-bar {
2135
  display: flex;
2136
  gap: 8px;
2137
+ padding: 14px 24px;
2138
  border-bottom: 1px solid var(--border-subtle);
2139
  flex-shrink: 0;
2140
+ background: rgba(20, 18, 14, 0.70);
2141
  }
2142
 
2143
  .diagram-type-btn {
2144
  display: flex;
2145
  flex-direction: column;
2146
  align-items: flex-start;
2147
+ gap: 3px;
2148
+ /* More generous padding β€” these are feature entry points, not list items */
2149
+ padding: 11px 18px;
2150
+ border-radius: var(--radius-md);
2151
  border: 1px solid var(--border);
2152
  background: transparent;
2153
  cursor: pointer;
2154
+ /* position: relative anchors the ::before gradient top-edge line */
2155
+ position: relative;
2156
+ overflow: hidden;
2157
+ transition: background var(--transition), border-color var(--transition), box-shadow var(--transition);
2158
+ min-width: 150px;
2159
  }
2160
+
2161
+ /* "Lit edge" technique β€” a gradient line materialises at the top of the
2162
+ active card, mimicking light catching a raised edge. Seen on Linear,
2163
+ Vercel, Raycast. Invisible by default; only the active card shows it. */
2164
+ .diagram-type-btn::before {
2165
+ content: '';
2166
+ position: absolute;
2167
+ top: 0; left: 12px; right: 12px;
2168
+ height: 2px;
2169
+ border-radius: 0 0 2px 2px;
2170
+ background: linear-gradient(90deg, transparent, var(--accent), var(--accent-soft), transparent);
2171
+ opacity: 0;
2172
+ transition: opacity var(--transition);
2173
+ }
2174
+
2175
  .diagram-type-btn:hover {
2176
  background: rgba(237,228,206,0.04);
2177
  border-color: var(--accent-border);
2178
  }
2179
  .diagram-type-btn.active {
2180
+ background: rgba(212,132,90,0.12);
2181
+ border-color: rgba(212,132,90,0.45);
2182
+ box-shadow: 0 4px 20px rgba(212,132,90,0.08), inset 0 0 0 0 transparent;
2183
  }
2184
+ .diagram-type-btn.active::before { opacity: 1; }
2185
 
2186
  .diagram-type-icon {
2187
+ /* Block display so the SVG sits on its own line above the label */
2188
+ display: flex;
2189
+ align-items: center;
2190
+ margin-bottom: 4px;
2191
+ color: var(--muted);
2192
+ transition: color var(--transition);
2193
  }
2194
+ .diagram-type-btn.active .diagram-type-icon,
2195
+ .diagram-type-btn:hover .diagram-type-icon { color: var(--accent-soft); }
2196
+
2197
  .diagram-type-label {
2198
+ font-size: 13px;
2199
  font-weight: 600;
2200
  color: var(--text);
2201
  font-family: var(--mono);
2202
+ letter-spacing: -0.01em;
2203
  }
2204
  .diagram-type-btn.active .diagram-type-label { color: var(--accent); }
2205
 
2206
+ /* text-2 not muted β€” the description is the context, not decoration */
2207
  .diagram-type-desc {
2208
+ font-size: 11px;
2209
+ color: var(--text-2);
2210
+ letter-spacing: -0.01em;
2211
  }
2212
 
2213
  /* ── Canvas ── */