fix(frontend): scroll the grid to follow the keyboard focus
deploy / deploy (push) Successful in 17s
deploy / deploy (push) Successful in 17s
Arrowing up/down moved the focus ring but the view didn't follow: the
card was scrolled with scrollIntoView({block:'nearest'}), which aligns to
the scroller's edges and is unaware of the fixed bottom navbar overlaying
the scroll area — so the newly focused row slid under the navbar. Replace
it with a manual scroll that keeps the focused card inside the scroller
with a top margin and a bottom margin sized for the navbar.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -71,12 +71,29 @@
|
||||
focusedId = files[next]?.id ?? null;
|
||||
if (next >= files.length - gridCols() * 2 && hasMore && !loading) void loadMore();
|
||||
const id = focusedId;
|
||||
requestAnimationFrame(() => {
|
||||
const idx = files.findIndex((f) => f.id === id);
|
||||
scrollContainer
|
||||
?.querySelector<HTMLElement>(`[data-file-index="${idx}"]`)
|
||||
?.scrollIntoView({ block: 'nearest' });
|
||||
});
|
||||
requestAnimationFrame(() => keepFocusedInView(id));
|
||||
}
|
||||
|
||||
// Keep the focused card within the scroller, leaving a margin at the bottom for
|
||||
// the fixed navbar (which overlaps the scroll area and otherwise hides the row
|
||||
// the focus moves onto). scrollIntoView can't account for that overlay.
|
||||
const FOCUS_MARGIN_TOP = 8;
|
||||
const FOCUS_MARGIN_BOTTOM = 72; // ~navbar height + gap
|
||||
|
||||
function keepFocusedInView(id: string | null) {
|
||||
if (!id || !scrollContainer) return;
|
||||
const idx = files.findIndex((f) => f.id === id);
|
||||
const card = scrollContainer.querySelector<HTMLElement>(`[data-file-index="${idx}"]`);
|
||||
if (!card) return;
|
||||
const cardRect = card.getBoundingClientRect();
|
||||
const scRect = scrollContainer.getBoundingClientRect();
|
||||
const top = cardRect.top - scRect.top;
|
||||
const bottom = cardRect.bottom - scRect.top;
|
||||
if (top < FOCUS_MARGIN_TOP) {
|
||||
scrollContainer.scrollTop += top - FOCUS_MARGIN_TOP;
|
||||
} else if (bottom > scRect.height - FOCUS_MARGIN_BOTTOM) {
|
||||
scrollContainer.scrollTop += bottom - (scRect.height - FOCUS_MARGIN_BOTTOM);
|
||||
}
|
||||
}
|
||||
|
||||
// Action keys operate on the selection; with nothing selected they fall back to
|
||||
|
||||
Reference in New Issue
Block a user