cleanup: stats activity chart — extract 30-day bar inline styles
Continuing the renderer-stats.ts inline-style extraction. The
"Aktivitaet (letzte 30 Tage)" bar chart built each day-column as
a 5-inline-style template:
<div style="flex: 1; display:flex; flex-direction:column;
align-items:center; gap:4px; min-width:0;">
<div style="width: 100%; height: 90px; display:flex;
align-items: flex-end;">
<div style="width:100%; height: 70%;
background: var(--accent, #9146ff);
border-radius: 2px 2px 0 0;" title="...">
<div style="font-size: 9px; color: var(--text-secondary);
white-space: nowrap;">
30 columns rendered per refresh meant ~7.5KB of duplicated inline
style attribute strings in the DOM after every refresh.
Extracted to .stats-day-col + .stats-day-bar-track + .stats-day-bar-
fill + .stats-day-label, plus .stats-activity-row + .stats-activity-
summary for the outer wrappers. Only the per-day height percent
stays inline (it's truly dynamic, per-day data).
Polish riders:
- Bar fill picks up height: 0.3s ease-out transition so the bars
animate up on data refresh instead of snapping
- Hover state shifts the bar from accent to accent-hover so the
hovered day reads as the focus
- Day-label spans get tabular-nums so the "05-12" type strings
align column-to-column
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
162b2845aa
commit
c9a5223eb6
@ -108,7 +108,7 @@ function renderStatsActivity(days: ArchiveStatsDay[]): void {
|
|||||||
|
|
||||||
const maxCount = days.reduce((m, d) => Math.max(m, d.count), 0);
|
const maxCount = days.reduce((m, d) => Math.max(m, d.count), 0);
|
||||||
if (maxCount === 0) {
|
if (maxCount === 0) {
|
||||||
applyHtml(container, `<div style="color: var(--text-secondary);">${escapeStatsHtml(UI_TEXT.static.statsActivityEmpty)}</div>`);
|
applyHtml(container, `<div class="form-note">${escapeStatsHtml(UI_TEXT.static.statsActivityEmpty)}</div>`);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -118,11 +118,11 @@ function renderStatsActivity(days: ArchiveStatsDay[]): void {
|
|||||||
const showLabel = idx === 0 || idx === days.length - 1 || idx % 7 === 0;
|
const showLabel = idx === 0 || idx === days.length - 1 || idx % 7 === 0;
|
||||||
const dayLabel = showLabel ? d.date.slice(5) : '';
|
const dayLabel = showLabel ? d.date.slice(5) : '';
|
||||||
return `
|
return `
|
||||||
<div style="flex: 1; display:flex; flex-direction:column; align-items:center; gap:4px; min-width:0;">
|
<div class="stats-day-col">
|
||||||
<div style="width: 100%; height: 90px; display:flex; align-items: flex-end;">
|
<div class="stats-day-bar-track">
|
||||||
<div style="width:100%; height: ${heightPct}%; background: var(--accent, #9146ff); border-radius: 2px 2px 0 0;" title="${escapeStatsHtml(tooltip)}"></div>
|
<div class="stats-day-bar-fill" style="height: ${heightPct}%;" title="${escapeStatsHtml(tooltip)}"></div>
|
||||||
</div>
|
</div>
|
||||||
<div style="font-size: 9px; color: var(--text-secondary); white-space: nowrap;">${escapeStatsHtml(dayLabel)}</div>
|
<div class="stats-day-label">${escapeStatsHtml(dayLabel)}</div>
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
}).join('');
|
}).join('');
|
||||||
@ -130,8 +130,8 @@ function renderStatsActivity(days: ArchiveStatsDay[]): void {
|
|||||||
const totalCount = days.reduce((s, d) => s + d.count, 0);
|
const totalCount = days.reduce((s, d) => s + d.count, 0);
|
||||||
const totalBytes = days.reduce((s, d) => s + d.bytes, 0);
|
const totalBytes = days.reduce((s, d) => s + d.bytes, 0);
|
||||||
applyHtml(container, `
|
applyHtml(container, `
|
||||||
<div style="display:flex; gap:2px; align-items: flex-end; padding: 6px 0;">${bars}</div>
|
<div class="stats-activity-row">${bars}</div>
|
||||||
<div style="font-size: 12px; color: var(--text-secondary); margin-top: 6px;">${escapeStatsHtml(UI_TEXT.static.statsActivitySummary
|
<div class="stats-activity-summary">${escapeStatsHtml(UI_TEXT.static.statsActivitySummary
|
||||||
.replace('{count}', String(totalCount))
|
.replace('{count}', String(totalCount))
|
||||||
.replace('{size}', formatBytesForStats(totalBytes)))}</div>
|
.replace('{size}', formatBytesForStats(totalBytes)))}</div>
|
||||||
`);
|
`);
|
||||||
|
|||||||
@ -2311,6 +2311,56 @@ select option {
|
|||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 30-day activity chart — vertical bar per day with optional date
|
||||||
|
label below every 7th column. */
|
||||||
|
.stats-activity-row {
|
||||||
|
display: flex;
|
||||||
|
gap: 2px;
|
||||||
|
align-items: flex-end;
|
||||||
|
padding: 6px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stats-day-col {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
gap: 4px;
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stats-day-bar-track {
|
||||||
|
width: 100%;
|
||||||
|
height: 90px;
|
||||||
|
display: flex;
|
||||||
|
align-items: flex-end;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stats-day-bar-fill {
|
||||||
|
width: 100%;
|
||||||
|
background: var(--accent, #9146ff);
|
||||||
|
border-radius: 2px 2px 0 0;
|
||||||
|
transition: height 0.3s ease-out, background 0.2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stats-day-bar-fill:hover {
|
||||||
|
background: var(--accent-hover, #b97aff);
|
||||||
|
}
|
||||||
|
|
||||||
|
.stats-day-label {
|
||||||
|
font-size: 9px;
|
||||||
|
color: var(--text-secondary);
|
||||||
|
white-space: nowrap;
|
||||||
|
font-variant-numeric: tabular-nums;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stats-activity-summary {
|
||||||
|
font-size: 12px;
|
||||||
|
color: var(--text-secondary);
|
||||||
|
margin-top: 6px;
|
||||||
|
font-variant-numeric: tabular-nums;
|
||||||
|
}
|
||||||
|
|
||||||
/* Old generic scrollbar rules were dead — superseded by the
|
/* Old generic scrollbar rules were dead — superseded by the
|
||||||
purple-themed *::-webkit-scrollbar block further down the file.
|
purple-themed *::-webkit-scrollbar block further down the file.
|
||||||
Removed to avoid confusion when someone greps for scrollbar styles. */
|
Removed to avoid confusion when someone greps for scrollbar styles. */
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user