From 8369950574903706cb987685b490772f2d91c7ae Mon Sep 17 00:00:00 2001 From: Amolith Date: Sat, 8 Nov 2025 17:27:46 -0700 Subject: [PATCH] fix(frontend): scroll only on local actions Previously, the selected item would scroll into view on every render, including when receiving updates from other clients. Now scrolling only occurs when the user performs a local action (voting, deleting, or navigating with keyboard). Assisted-by: Claude Sonnet 4.5 via Crush --- static/app.js | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/static/app.js b/static/app.js index f3fd79afa9d10df5cb391b4a12f9da4866dc85e5..711d9377db4eb9858d4f546a914b6e2d52788bd7 100644 --- a/static/app.js +++ b/static/app.js @@ -14,6 +14,7 @@ let selectedItemId = null; // For keyboard navigation let selectedPosition = null; // Position to restore after voting let lastSyncTime = null; // For connection status let isReady = false; // Track if initial state received +let shouldScrollSelectedIntoView = false; // Only scroll on local actions const CHECK_ICON_SVG = ``; @@ -322,6 +323,7 @@ function vote(itemId, voteType) { // Remember current position to select item at same position after re-sort const sorted = getSortedItems(); selectedPosition = sorted.findIndex(i => i.id === itemId); + shouldScrollSelectedIntoView = true; // Keep the button visually pressed briefly to avoid flicker const btn = document.querySelector(`[data-item-id="${itemId}"] [data-action="vote"][data-vote-type="${voteType}"]`); @@ -341,6 +343,7 @@ function vote(itemId, voteType) { function deleteItem(itemId) { if (confirm('Delete this item?')) { + shouldScrollSelectedIntoView = true; sendMessage({ type: 'delete_item', itemId }); } } @@ -457,12 +460,14 @@ document.addEventListener('keydown', (e) => { const currentIdx = sorted.findIndex(i => i.id === selectedItemId); const nextIdx = Math.min(currentIdx + 1, sorted.length - 1); selectedItemId = sorted[nextIdx].id; + shouldScrollSelectedIntoView = true; render(); } else if (e.key === 'k' || e.key === 'ArrowUp') { e.preventDefault(); const currentIdx = sorted.findIndex(i => i.id === selectedItemId); const prevIdx = Math.max(currentIdx - 1, 0); selectedItemId = sorted[prevIdx].id; + shouldScrollSelectedIntoView = true; render(); } @@ -674,12 +679,13 @@ function render() { } }); - // Scroll selected item into view - if (selectedItemId) { + // Scroll selected item into view on local actions + if (shouldScrollSelectedIntoView && selectedItemId) { const selectedEl = listContainer.querySelector(`[data-item-id="${selectedItemId}"]`); if (selectedEl) { selectedEl.scrollIntoView({ block: 'nearest', behavior: 'smooth' }); } + shouldScrollSelectedIntoView = false; } }