Commitdebcf27unknown_key
feat(design): Phase 3 — app shell chrome (repo header, nav, lists)
feat(design): Phase 3 — app shell chrome (repo header, nav, lists) Refines the high-leverage chrome that renders on every app page. Strategy: don't rewrite 50+ route views — refine the class surface they all inherit. Token + class updates flow through automatically. components.tsx - RepoHeader: title row uses display font + new .repo-header-title flex; status pills extracted from inline styles to .repo-header-pill / -archived / -template classes. Forked-from line uses mono caption. - RepoNav: 4 AI links (Explain / Ask / Spec / Tests) lose hardcoded #bc8cff inline color in favour of .repo-nav-ai class — picks up the refined --accent token + faint hover background. Active state on Explain still works via class concat. layout.tsx CSS additions/refinements - .repo-header (display font, flex-wrap, refined fork caption) - .repo-header-pill / -archived / -template (mono uppercase chips) - .repo-nav (gradient underline on .active replacing solid border-bottom) - .repo-nav-ai (accent color + faint-gradient hover, !important to win against any inline style holdouts) - .breadcrumb (mono feature settings, stronger active strong color) - .page-header (NEW utility: eyebrow + title + actions, dashboard / settings / admin can adopt incrementally — divider hairline at base) - .file-table (filenames now mono with feature settings, tighter rows, accent color on hover, subtle border between rows) - .commit-item (display font on messages, mono on meta, gradient-faint hover on .commit-sha pill, accent color, tighter letter-spacing) - .issue-item (display font on titles, mono on meta, accent on hover) Tests: 1226 pass / 1 unrelated pre-existing fail.
2 files changed+191−47debcf276726378dc5a84e10f30f4ddb2ad05daad
2 changed files+191−47
Modifiedsrc/views/components.tsx+9−11View fileUnifiedSplit
@@ -26,7 +26,7 @@ export const RepoHeader: FC<{
2626}) => (
2727 <div class="repo-header">
2828 <div>
29 <div style="display: flex; align-items: center; gap: 8px; font-size: 20px">
29 <div class="repo-header-title">
3030 <a href={`/${owner}`} class="owner">
3131 {owner}
3232 </a>
@@ -36,8 +36,7 @@ export const RepoHeader: FC<{
3636 </a>
3737 {archived && (
3838 <span
39 class="badge"
40 style="background:var(--bg-secondary);color:var(--text-muted);font-size:11px;padding:2px 8px;border-radius:10px;text-transform:uppercase;letter-spacing:0.5px"
39 class="repo-header-pill repo-header-pill-archived"
4140 title="Read-only: pushes and new issues/PRs disabled"
4241 >
4342 Archived
@@ -45,8 +44,7 @@ export const RepoHeader: FC<{
4544 )}
4645 {isTemplate && (
4746 <span
48 class="badge"
49 style="background:var(--bg-secondary);color:var(--accent);font-size:11px;padding:2px 8px;border-radius:10px;text-transform:uppercase;letter-spacing:0.5px"
47 class="repo-header-pill repo-header-pill-template"
5048 title="This repository can be used as a template"
5149 >
5250 Template
@@ -54,7 +52,7 @@ export const RepoHeader: FC<{
5452 )}
5553 </div>
5654 {forkedFrom && (
57 <div style="font-size: 12px; color: var(--text-muted); margin-top: 2px">
55 <div class="repo-header-fork">
5856 forked from <a href={`/${forkedFrom}`}>{forkedFrom}</a>
5957 </div>
6058 )}
@@ -166,24 +164,24 @@ export const RepoNav: FC<{
166164 </a>
167165 <a
168166 href={`/${owner}/${repo}/explain`}
169 class={active === "explain" ? "active" : ""}
170 style="margin-left: auto; color: #bc8cff"
167 class={`repo-nav-ai${active === "explain" ? " active" : ""}`}
168 style="margin-left: auto"
171169 >
172170 {"\u2728"} Explain
173171 </a>
174 <a href={`/${owner}/${repo}/ask`} style="color: #bc8cff">
172 <a href={`/${owner}/${repo}/ask`} class="repo-nav-ai">
175173 {"\u2728"} Ask AI
176174 </a>
177175 <a
178176 href={`/${owner}/${repo}/spec`}
179 style="color: #bc8cff"
177 class="repo-nav-ai"
180178 title="Spec to PR — paste a feature spec, AI opens a draft PR"
181179 >
182180 {"\u2728"} Spec
183181 </a>
184182 <a
185183 href={`/${owner}/${repo}/ai/tests`}
186 style="color: #bc8cff"
184 class="repo-nav-ai"
187185 title="AI Tests \u2014 generate failing test stubs from a source file"
188186 >
189187 {"\u2728"} Tests
Modifiedsrc/views/layout.tsx+182−36View fileUnifiedSplit
@@ -1135,54 +1135,159 @@ const css = `
11351135 .repo-header {
11361136 display: flex;
11371137 align-items: center;
1138 gap: 8px;
1139 margin-bottom: 18px;
1140 font-size: var(--t-lg);
1141 letter-spacing: -0.015em;
1138 gap: 12px;
1139 margin-bottom: 22px;
1140 }
1141 .repo-header-title {
1142 display: flex;
1143 align-items: center;
1144 gap: 10px;
1145 font-family: var(--font-display);
1146 font-size: 24px;
1147 letter-spacing: -0.025em;
1148 flex-wrap: wrap;
1149 }
1150 .repo-header .owner {
1151 color: var(--text-muted);
1152 font-weight: 500;
1153 transition: color var(--t-fast) var(--ease);
1154 }
1155 .repo-header .owner:hover { color: var(--text-link); text-decoration: none; }
1156 .repo-header .separator { color: var(--text-faint); font-weight: 300; }
1157 .repo-header .name {
1158 color: var(--text-strong);
1159 font-weight: 700;
1160 letter-spacing: -0.028em;
11421161 }
1143 .repo-header .owner { color: var(--text-link); font-weight: 500; }
1144 .repo-header .separator { color: var(--text-faint); }
1145 .repo-header .name { color: var(--text); font-weight: 700; }
11461162 .repo-header .name:hover { color: var(--text-link); text-decoration: none; }
1163 .repo-header-fork {
1164 font-family: var(--font-mono);
1165 font-size: 11px;
1166 color: var(--text-muted);
1167 margin-top: 4px;
1168 letter-spacing: 0.01em;
1169 }
1170 .repo-header-fork a { color: var(--text-muted); }
1171 .repo-header-fork a:hover { color: var(--accent); }
1172 .repo-header-pill {
1173 display: inline-flex;
1174 align-items: center;
1175 padding: 2px 10px;
1176 border-radius: var(--r-full);
1177 font-family: var(--font-mono);
1178 font-size: 10px;
1179 font-weight: 600;
1180 letter-spacing: 0.12em;
1181 text-transform: uppercase;
1182 line-height: 1.6;
1183 vertical-align: 4px;
1184 }
1185 .repo-header-pill-archived {
1186 background: rgba(251,191,36,0.10);
1187 color: var(--yellow);
1188 border: 1px solid rgba(251,191,36,0.30);
1189 }
1190 .repo-header-pill-template {
1191 background: var(--accent-gradient-faint);
1192 color: var(--accent);
1193 border: 1px solid rgba(140,109,255,0.30);
1194 }
11471195 .repo-header-actions { margin-left: auto; display: flex; gap: 8px; align-items: center; }
11481196
11491197 .repo-nav {
11501198 display: flex;
1151 gap: 2px;
1199 gap: 1px;
11521200 border-bottom: 1px solid var(--border);
1153 margin-bottom: 24px;
1201 margin-bottom: 28px;
11541202 overflow-x: auto;
11551203 scrollbar-width: thin;
11561204 }
11571205 .repo-nav::-webkit-scrollbar { height: 0; }
11581206 .repo-nav a {
1159 padding: 10px 14px;
1207 position: relative;
1208 padding: 11px 14px;
11601209 color: var(--text-muted);
11611210 border-bottom: 2px solid transparent;
11621211 font-size: var(--t-sm);
11631212 font-weight: 500;
11641213 margin-bottom: -1px;
1165 transition: all var(--t-fast) var(--ease);
1214 transition: color var(--t-fast) var(--ease), background var(--t-fast) var(--ease);
11661215 white-space: nowrap;
11671216 }
1168 .repo-nav a:hover { text-decoration: none; color: var(--text); background: var(--bg-hover); }
1217 .repo-nav a:hover { text-decoration: none; color: var(--text-strong); background: var(--bg-hover); }
11691218 .repo-nav a.active {
1170 color: var(--text);
1171 border-bottom-color: var(--accent);
1219 color: var(--text-strong);
1220 font-weight: 600;
1221 }
1222 .repo-nav a.active::after {
1223 content: '';
1224 position: absolute;
1225 left: 14px;
1226 right: 14px;
1227 bottom: -1px;
1228 height: 2px;
1229 background: var(--accent-gradient);
1230 border-radius: 2px;
1231 }
1232 /* AI links in the right-side cluster — sparkle accent */
1233 .repo-nav-ai {
1234 color: var(--accent) !important;
1235 font-weight: 500;
1236 }
1237 .repo-nav-ai:hover {
1238 color: var(--accent-hover) !important;
1239 background: var(--accent-gradient-faint) !important;
1240 }
1241 .repo-nav-ai.active {
1242 color: var(--accent-hover) !important;
11721243 font-weight: 600;
11731244 }
11741245
11751246 .breadcrumb {
11761247 display: flex;
1177 gap: 4px;
1248 gap: 6px;
11781249 align-items: center;
1179 margin-bottom: 16px;
1250 margin-bottom: 18px;
11801251 color: var(--text-muted);
11811252 font-size: var(--t-sm);
11821253 font-family: var(--font-mono);
1254 font-feature-settings: var(--mono-feat);
11831255 }
11841256 .breadcrumb a { color: var(--text-link); font-weight: 500; }
11851257 .breadcrumb a:hover { color: var(--accent-hover); }
1258 .breadcrumb strong {
1259 color: var(--text-strong);
1260 font-weight: 600;
1261 }
1262
1263 /* Page header — eyebrow + title + optional actions row.
1264 Use on dashboard, settings, admin, any "section landing" page. */
1265 .page-header {
1266 display: flex;
1267 align-items: flex-end;
1268 justify-content: space-between;
1269 gap: 16px;
1270 margin-bottom: 28px;
1271 padding-bottom: 20px;
1272 border-bottom: 1px solid var(--border-subtle);
1273 flex-wrap: wrap;
1274 }
1275 .page-header-text { flex: 1; min-width: 280px; }
1276 .page-header .eyebrow { margin-bottom: var(--s-2); }
1277 .page-header h1 {
1278 font-family: var(--font-display);
1279 font-size: clamp(24px, 3vw, 36px);
1280 line-height: 1.1;
1281 letter-spacing: -0.028em;
1282 margin-bottom: 6px;
1283 }
1284 .page-header p {
1285 color: var(--text-muted);
1286 font-size: var(--t-sm);
1287 line-height: 1.55;
1288 max-width: 640px;
1289 }
1290 .page-header-actions { display: flex; gap: 8px; align-items: center; }
11861291
11871292 /* ============================================================ */
11881293 /* File browser table */
@@ -1193,14 +1298,29 @@ const css = `
11931298 border-radius: var(--r-md);
11941299 overflow: hidden;
11951300 background: var(--bg-elevated);
1301 border-collapse: collapse;
11961302 }
1197 .file-table tr { border-bottom: 1px solid var(--border); }
1303 .file-table tr { border-bottom: 1px solid var(--border-subtle); transition: background var(--t-fast) var(--ease); }
11981304 .file-table tr:last-child { border-bottom: none; }
1199 .file-table td { padding: 10px 16px; font-size: var(--t-sm); }
1305 .file-table td {
1306 padding: 9px 16px;
1307 font-size: var(--t-sm);
1308 font-family: var(--font-mono);
1309 font-feature-settings: var(--mono-feat);
1310 }
12001311 .file-table tr:hover { background: var(--bg-hover); }
1201 .file-icon { width: 22px; color: var(--text-faint); font-family: var(--font-mono); font-size: var(--t-sm); }
1202 .file-name a { color: var(--text); font-weight: 500; }
1203 .file-name a:hover { color: var(--text-link); text-decoration: none; }
1312 .file-icon {
1313 width: 22px;
1314 color: var(--text-faint);
1315 font-size: 13px;
1316 text-align: center;
1317 }
1318 .file-name a {
1319 color: var(--text);
1320 font-weight: 500;
1321 transition: color var(--t-fast) var(--ease);
1322 }
1323 .file-name a:hover { color: var(--accent); text-decoration: none; }
12041324
12051325 /* ============================================================ */
12061326 /* Blob view */
@@ -1254,26 +1374,45 @@ const css = `
12541374 display: flex;
12551375 justify-content: space-between;
12561376 align-items: center;
1257 padding: 14px 16px;
1258 border-bottom: 1px solid var(--border);
1377 padding: 14px 18px;
1378 border-bottom: 1px solid var(--border-subtle);
12591379 transition: background var(--t-fast) var(--ease);
12601380 }
12611381 .commit-item:last-child { border-bottom: none; }
12621382 .commit-item:hover { background: var(--bg-hover); }
1263 .commit-message { font-size: var(--t-sm); font-weight: 500; line-height: 1.45; }
1264 .commit-meta { font-size: var(--t-xs); color: var(--text-muted); margin-top: 4px; }
1383 .commit-message {
1384 font-size: var(--t-sm);
1385 font-weight: 500;
1386 line-height: 1.45;
1387 color: var(--text-strong);
1388 letter-spacing: -0.005em;
1389 }
1390 .commit-meta {
1391 font-family: var(--font-mono);
1392 font-size: 11px;
1393 color: var(--text-muted);
1394 margin-top: 5px;
1395 letter-spacing: 0.01em;
1396 }
12651397 .commit-sha {
12661398 font-family: var(--font-mono);
1267 font-size: var(--t-xs);
1268 padding: 3px 8px;
1399 font-feature-settings: var(--mono-feat);
1400 font-size: 11px;
1401 padding: 4px 9px;
12691402 background: var(--bg-tertiary);
12701403 border: 1px solid var(--border);
12711404 border-radius: var(--r-sm);
1272 color: var(--text-link);
1273 font-weight: 500;
1405 color: var(--accent);
1406 font-weight: 600;
1407 letter-spacing: 0.02em;
12741408 transition: all var(--t-fast) var(--ease);
12751409 }
1276 .commit-sha:hover { border-color: var(--border-strong); color: var(--accent-hover); }
1410 .commit-sha:hover {
1411 border-color: rgba(140,109,255,0.40);
1412 background: var(--accent-gradient-faint);
1413 color: var(--accent-hover);
1414 text-decoration: none;
1415 }
12771416
12781417 .diff-view { margin-top: 16px; }
12791418 .diff-file {
@@ -1630,14 +1769,21 @@ const css = `
16301769 .state-open { color: var(--green); }
16311770 .state-closed { color: #b69dff; }
16321771 .issue-title {
1633 font-size: var(--t-base);
1772 font-family: var(--font-display);
1773 font-size: var(--t-md);
16341774 font-weight: 600;
1635 line-height: 1.4;
1636 letter-spacing: -0.005em;
1775 line-height: 1.35;
1776 letter-spacing: -0.012em;
1777 }
1778 .issue-title a { color: var(--text-strong); transition: color var(--t-fast) var(--ease); }
1779 .issue-title a:hover { color: var(--accent); text-decoration: none; }
1780 .issue-meta {
1781 font-family: var(--font-mono);
1782 font-size: 11px;
1783 color: var(--text-muted);
1784 margin-top: 5px;
1785 letter-spacing: 0.01em;
16371786 }
1638 .issue-title a { color: var(--text); }
1639 .issue-title a:hover { color: var(--text-link); text-decoration: none; }
1640 .issue-meta { font-size: var(--t-xs); color: var(--text-muted); margin-top: 4px; }
16411787
16421788 .issue-badge {
16431789 display: inline-flex;
16441790