Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 18 additions & 10 deletions site/src/scripts/techapi.js
Original file line number Diff line number Diff line change
Expand Up @@ -282,16 +282,24 @@ function countUp(node, target, opts = {}) {
const maxTotal = Math.max(...points.map((point) => point.total));
const minTotal = Math.min(...points.map((point) => point.total));
const range = Math.max(1, maxTotal - minTotal);
chartEl.innerHTML = points.map((point) => {
const pct = 18 + ((point.total - minTotal) / range) * 82;
const deltaText = formatDelta(point.delta, point.baseline);
const deltaClass = point.delta < 0 ? " is-negative" : "";
return `<a class="history-bar" href="${esc(point.url)}" target="_blank" rel="noopener" style="--h:${pct.toFixed(1)}%" title="${esc(point.title)}">
<span class="history-bar-fill"></span>
<span class="history-bar-total">${point.total.toLocaleString()}</span>
<span class="history-bar-delta${deltaClass}">${esc(deltaText)}</span>
</a>`;
}).join("");
// Growth curve: every sync as a point on an area chart scaled to the panel
// width, so the whole timeline fits with nothing clipped or scrolled.
const VW = 1000, VH = 150, PAD = 6;
const xs = (i) => PAD + (points.length < 2 ? 0 : (i / (points.length - 1)) * (VW - 2 * PAD));
const ys = (t) => VH - PAD - ((t - minTotal) / range) * (VH - 2 * PAD);
const line = points.map((p, i) => `${i ? "L" : "M"}${xs(i).toFixed(1)} ${ys(p.total).toFixed(1)}`).join(" ");
const area = `${line} L${xs(points.length - 1).toFixed(1)} ${VH} L${xs(0).toFixed(1)} ${VH} Z`;
const last = points[points.length - 1];
chartEl.innerHTML = `<svg class="history-svg" viewBox="0 0 ${VW} ${VH}" preserveAspectRatio="none" aria-label="Dataset growth curve">
<defs><linearGradient id="histfill" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="var(--accent)" stop-opacity=".34"></stop>
<stop offset="100%" stop-color="var(--accent)" stop-opacity="0"></stop>
</linearGradient></defs>
<path d="${area}" fill="url(#histfill)"></path>
<path d="${line}" fill="none" stroke="var(--accent)" stroke-width="2" vector-effect="non-scaling-stroke" stroke-linejoin="round" stroke-linecap="round"></path>
</svg>
<span class="history-cap history-cap-lo">${esc(points[0].when)} · ${minTotal.toLocaleString()}</span>
<span class="history-cap history-cap-hi">${esc(last.when)} · ${last.total.toLocaleString()}</span>`;

// Show every sync (newest first), growth-first. The list scrolls (CSS
// max-height) so the full history stays reachable without a giant section.
Expand Down
91 changes: 31 additions & 60 deletions site/src/styles/techapi.css
Original file line number Diff line number Diff line change
Expand Up @@ -252,14 +252,17 @@ code, .mono { font-family: var(--mono); }
============================================================ */
.history {
display: grid;
grid-template-columns: .9fr 1.1fr;
grid-template-columns: 1fr 1.15fr;
gap: 16px;
align-items: start;
}
.history-panel {
border: 1px solid var(--border);
border-radius: 8px;
background: var(--surface);
padding: 22px;
padding: 24px;
display: flex;
flex-direction: column;
}
.history-label {
font-family: var(--mono);
Expand All @@ -279,22 +282,22 @@ code, .mono { font-family: var(--mono); }
.history-grid {
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: 8px;
gap: 9px;
margin-top: 22px;
}
.history-count {
display: flex;
align-items: center;
justify-content: space-between;
gap: 12px;
padding: 10px 12px;
padding: 13px 14px;
border: 1px solid var(--border);
border-radius: var(--radius);
background: var(--surface-2);
font-family: var(--mono);
}
.history-count span { color: var(--muted); font-size: 12px; }
.history-count b { color: var(--fg); font-size: 13px; }
.history-count span { color: var(--muted); font-size: 12.5px; }
.history-count b { color: var(--fg); font-size: 15px; }
.history-list {
list-style: none;
margin: 20px 0 0;
Expand All @@ -312,71 +315,39 @@ code, .mono { font-family: var(--mono); }
.history-list::-webkit-scrollbar-thumb { background: var(--border-strong); border-radius: 4px; }
.history-list::-webkit-scrollbar-track { background: transparent; }
.history-chart {
min-height: 210px;
position: relative;
height: 168px;
margin-top: 18px;
padding: 16px 12px 12px;
display: grid;
grid-auto-flow: column;
grid-auto-columns: minmax(62px, 1fr);
align-items: end;
gap: 10px;
overflow-x: auto;
border: 1px solid var(--border);
border-radius: var(--radius);
overflow: hidden;
background:
linear-gradient(to top, var(--border) 1px, transparent 1px) 0 25% / 100% 25%,
linear-gradient(to top, var(--grid-line) 1px, transparent 1px) 0 0 / 100% 25%,
var(--surface-2);
}
.history-empty {
align-self: center;
justify-self: center;
grid-column: 1 / -1;
.history-svg { display: block; width: 100%; height: 100%; }
.history-cap {
position: absolute;
bottom: 8px;
font-family: var(--mono);
font-size: 10.5px;
color: var(--muted);
font-size: 12px;
background: color-mix(in srgb, var(--surface-2) 72%, transparent);
padding: 1px 6px;
border-radius: 3px;
}
.history-bar {
min-width: 0;
height: 178px;
.history-cap-lo { left: 9px; }
.history-cap-hi { right: 9px; color: var(--accent-text); }
.history-empty {
position: absolute;
inset: 0;
display: grid;
grid-template-rows: 1fr auto auto;
gap: 6px;
color: var(--fg);
}
.history-bar-fill {
align-self: end;
min-height: 10px;
height: var(--h);
border: 1px solid color-mix(in srgb, var(--accent) 60%, var(--border));
border-radius: 4px 4px 2px 2px;
background:
linear-gradient(180deg, color-mix(in srgb, var(--accent) 92%, white 8%), var(--accent-deep));
box-shadow: 0 0 26px -12px var(--accent);
transition: filter .16s, transform .16s;
}
.history-bar:hover .history-bar-fill {
filter: brightness(1.08);
transform: translateY(-2px);
}
.history-bar-total,
.history-bar-delta {
min-width: 0;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
font-family: var(--mono);
place-items: center;
text-align: center;
}
.history-bar-total {
font-size: 11px;
font-weight: 700;
}
.history-bar-delta {
font-size: 10px;
color: var(--accent-text);
}
.history-bar-delta.is-negative {
color: var(--err);
padding: 0 16px;
font-family: var(--mono);
color: var(--muted);
font-size: 12px;
}
.history-list li {
display: grid;
Expand Down
Loading