fix(positioning): prevent canvas collapse on type/range toggle

- Lock #positioning-canvas min-height to current offsetHeight before each
  HTMX swap, release it in htmx:afterSwap — prevents flash-to-zero during
  Chart.js initialization in the new content
- Add CSS min-height:200px fallback on all canvas containers so they never
  fully collapse even before JS runs
- Extract _swapCanvas() helper to deduplicate setRange/setType logic

Root cause of visual collapse: cot_positioning_combined table missing
(needs sqlmesh plan prod + export_serving to materialize).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Deeman
2026-02-26 20:04:19 +01:00
parent d3c9d95386
commit 8f97c6b0c9
2 changed files with 19 additions and 5 deletions

View File

@@ -72,24 +72,29 @@ function _positioningUrl() {
return POSITIONING_URL + '?range=' + currentRange + '&type=' + currentType;
}
function _swapCanvas(url) {
var el = document.getElementById('positioning-canvas');
el.style.minHeight = el.offsetHeight + 'px';
el.classList.add('canvas-loading');
htmx.ajax('GET', url, { target: '#positioning-canvas', swap: 'innerHTML' });
}
function setRange(val) {
currentRange = val;
var url = _positioningUrl();
window.history.pushState({}, '', url);
document.getElementById('positioning-canvas').classList.add('canvas-loading');
htmx.ajax('GET', url, { target: '#positioning-canvas', swap: 'innerHTML' });
_swapCanvas(url);
}
function setType(val) {
currentType = val;
var url = _positioningUrl();
window.history.pushState({}, '', url);
document.getElementById('positioning-canvas').classList.add('canvas-loading');
htmx.ajax('GET', url, { target: '#positioning-canvas', swap: 'innerHTML' });
// Sync type pill active state immediately (canvas swap will also re-sync)
document.querySelectorAll('#type-pills .filter-pill').forEach(function (btn) {
btn.classList.toggle('active', btn.textContent.trim() === (val === 'combined' ? 'F+O Combined' : 'Futures'));
});
_swapCanvas(url);
}
// MA toggles: client-side only — update Chart.js dataset visibility
@@ -103,7 +108,9 @@ function toggleMA(key) {
document.addEventListener('htmx:afterSwap', function (e) {
if (e.detail.target.id === 'positioning-canvas') {
document.getElementById('positioning-canvas').classList.remove('canvas-loading');
var el = document.getElementById('positioning-canvas');
el.classList.remove('canvas-loading');
el.style.minHeight = ''; // release height lock
requestAnimationFrame(function() {
['priceChart', 'cotChart'].forEach(function(id) {
var c = Chart.getChart(id);

View File

@@ -736,6 +736,13 @@
transition: opacity 0.15s;
}
/* Prevent canvas from collapsing to 0 height during HTMX swaps.
Chart.js needs the container to have non-zero height before it can
measure the aspect ratio. min-height is locked in JS before each swap. */
#positioning-canvas, #supply-canvas, #warehouse-canvas, #weather-canvas {
min-height: 200px;
}
/* Freshness badges */
.freshness-bar {
display: flex;