Items-list sparklines, retro CSS, pinned tooling, deploy docs
- Bulk-load recent price points per item and render a sparkline in the items list (new LoadRecentPriceHistory query avoids N+1). - Add retro.css visual layer and refreshed login/items/layout styling. - Swap the logo from webp to avif. - Pin htmx/Chart.js/Tailwind/templ versions in the Makefile with vendor / tools / update-deps targets; README documents the dependency-bump flow and the hardened systemd deploy. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -9,7 +9,29 @@
|
||||
return;
|
||||
}
|
||||
var data = JSON.parse(canvas.dataset.chart);
|
||||
new Chart(canvas.getContext('2d'), {
|
||||
var ctx = canvas.getContext('2d');
|
||||
|
||||
// Vertical gradient fill — bright accent at the top, transparent at the
|
||||
// baseline — makes the chart read at a glance instead of as a thin line.
|
||||
var fill = ctx.createLinearGradient(0, 0, 0, canvas.clientHeight || 200);
|
||||
fill.addColorStop(0, 'rgba(0, 228, 164, 0.45)');
|
||||
fill.addColorStop(1, 'rgba(0, 228, 164, 0.00)');
|
||||
|
||||
// Chart.js plugin that paints a soft glow under the line stroke before
|
||||
// the dataset draws. Cheap enough to keep on by default; respects
|
||||
// prefers-reduced-motion only insofar as nothing animates here.
|
||||
var glowPlugin = {
|
||||
id: 'priceLineGlow',
|
||||
beforeDatasetDraw: function (chart) {
|
||||
var c = chart.ctx;
|
||||
c.save();
|
||||
c.shadowColor = 'rgba(0, 228, 164, 0.55)';
|
||||
c.shadowBlur = 12;
|
||||
},
|
||||
afterDatasetDraw: function (chart) { chart.ctx.restore(); }
|
||||
};
|
||||
|
||||
new Chart(ctx, {
|
||||
type: 'line',
|
||||
data: {
|
||||
labels: data.labels,
|
||||
@@ -17,19 +39,37 @@
|
||||
label: 'Best price',
|
||||
data: data.points,
|
||||
borderColor: '#00e4a4',
|
||||
backgroundColor: 'rgba(0,228,164,0.15)',
|
||||
pointBackgroundColor: '#e84040',
|
||||
borderWidth: 2.5,
|
||||
backgroundColor: fill,
|
||||
pointBackgroundColor: '#ffffff',
|
||||
pointBorderColor: '#00e4a4',
|
||||
pointBorderWidth: 1.5,
|
||||
pointRadius: 3,
|
||||
tension: 0.25,
|
||||
pointHoverRadius: 5,
|
||||
tension: 0.3,
|
||||
fill: true
|
||||
}]
|
||||
},
|
||||
options: {
|
||||
responsive: true,
|
||||
maintainAspectRatio: false,
|
||||
interaction: { mode: 'index', intersect: false },
|
||||
scales: {
|
||||
x: { ticks: { color: '#a8c0f0' }, grid: { color: 'rgba(255,255,255,0.07)' } },
|
||||
y: { ticks: { color: '#a8c0f0' }, grid: { color: 'rgba(255,255,255,0.07)' } }
|
||||
x: { ticks: { color: '#a8c0f0' }, grid: { color: 'rgba(255,255,255,0.06)' } },
|
||||
y: { ticks: { color: '#a8c0f0' }, grid: { color: 'rgba(255,255,255,0.06)' } }
|
||||
},
|
||||
plugins: { legend: { labels: { color: '#ffffff' } } }
|
||||
}
|
||||
plugins: {
|
||||
legend: { labels: { color: '#ffffff' } },
|
||||
tooltip: {
|
||||
backgroundColor: 'rgba(20, 32, 80, 0.95)',
|
||||
borderColor: 'rgba(0, 164, 228, 0.6)',
|
||||
borderWidth: 1,
|
||||
titleColor: '#ffffff',
|
||||
bodyColor: '#a8c0f0',
|
||||
padding: 10
|
||||
}
|
||||
}
|
||||
},
|
||||
plugins: [glowPlugin]
|
||||
});
|
||||
})();
|
||||
|
||||
Reference in New Issue
Block a user