fix(frontend): scroll only on local actions
Amolith
created 2 months ago
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
Change summary
static/app.js | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)
Detailed changes
@@ -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 = `<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-check"><polyline points="20 6 9 17 4 12"></polyline></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;
}
}