diff --git a/site/src/scripts/techapi.js b/site/src/scripts/techapi.js index 88650e48f1c..71e5ed53356 100644 --- a/site/src/scripts/techapi.js +++ b/site/src/scripts/techapi.js @@ -263,6 +263,20 @@ function countUp(node, target, opts = {}) { return "no change"; } + // Most dump commits share one boilerplate title ("chore(site): refresh public + // dump for X import"). The timeline is about growth, not commit messages, so we + // strip the conventional-commit prefix and the dump-refresh boilerplate and keep + // only the distinctive bit (e.g. "GSMArena Kaggle"), or "" when there is none. + function shortTitle(raw) { + let t = String(raw || "").trim(); + if (/^revert\b/i.test(t)) return "reverted"; + t = t.replace(/^[a-z]+(\([^)]*\))?:\s*/i, ""); // drop "chore(site): " + const m = t.match(/\bdump\s+(?:for|after)\s+(.+?)(?:\s+imports?)?\s*$/i); + if (m) return m[1].trim(); + if (/\b(refresh|regenerate|update)\b.*\bdump\b/i.test(t)) return ""; // pure boilerplate + return t; // genuinely distinctive + } + function renderHistory(points) { if (!points.length) throw new Error("empty history"); const maxTotal = Math.max(...points.map((point) => point.total)); @@ -279,15 +293,33 @@ function countUp(node, target, opts = {}) { `; }).join(""); - listEl.innerHTML = points.slice().reverse().map((point) => { + // The chart already shows every sync; the list is the recent detail — cap it + // so the section stays compact, with a link to the full commit history. + const LIST_MAX = 8; + const recent = points.slice().reverse(); + const shown = recent.slice(0, LIST_MAX); + const rows = shown.map((point) => { const changes = point.changes.length ? point.changes.map((row) => `${shortLabel[row.key]} ${formatDelta(row.delta)}`).join(", ") : (point.baseline ? "baseline snapshot" : `total ${formatDelta(point.delta)}`); - return `
  • - ${esc(point.title)} - ${esc(point.when)} - ${esc(point.sha)} - ${esc(changes)} + const tag = shortTitle(point.title); + const delta = point.baseline ? "baseline" : formatDelta(point.delta); + return `
  • + + ${esc(point.when)} + ${point.total.toLocaleString()} + ${esc(delta)} + + ${esc(changes)}${tag ? ` · ${esc(tag)}` : ""}
  • `; - }).join(""); + }); + const hidden = recent.length - shown.length; + if (hidden > 0) { + rows.push(`
  • + ${hidden} earlier ${hidden === 1 ? "sync" : "syncs"} → +
  • `); + } + listEl.innerHTML = rows.join(""); } const fmtWhen = (date) => date diff --git a/site/src/styles/techapi.css b/site/src/styles/techapi.css index a80fc1b5482..41dfcb84586 100644 --- a/site/src/styles/techapi.css +++ b/site/src/styles/techapi.css @@ -383,18 +383,30 @@ code, .mono { font-family: var(--mono); } background: var(--accent); box-shadow: 0 0 0 4px color-mix(in srgb, var(--accent) 14%, transparent); } -.history-list a { +.history-item { min-width: 0; } +.history-head { + display: flex; + align-items: baseline; + gap: 10px; + flex-wrap: wrap; color: var(--fg); font-weight: 600; } -.history-list a:hover { color: var(--accent-text); } +.history-when { font-family: var(--mono); font-size: 12px; font-weight: 500; color: var(--muted); } +.history-recs { font-family: var(--mono); font-size: 14.5px; letter-spacing: -.01em; } +.history-delta { font-family: var(--mono); font-size: 12px; color: var(--accent-text); } +.history-delta.is-negative { color: var(--err); } +.history-head:hover .history-recs { color: var(--accent-text); } .history-list small { display: block; - margin-top: 2px; + margin-top: 3px; font-family: var(--mono); font-size: 11.5px; color: var(--muted); } +.history-more a { font-family: var(--mono); font-size: 12px; color: var(--muted); font-weight: 500; } +.history-more a:hover { color: var(--accent-text); } +.history-dot.is-faint { background: var(--faint); box-shadow: none; } @media (max-width: 760px) { .history { grid-template-columns: 1fr; } .history-grid { grid-template-columns: 1fr; }