fix(dashboard): keep an over-wide focused rail card in view

In a window narrower than a card (or under zoom), a focused card could
never fit, so its own snap offset fell short of the needed scroll and
the rail jumped to the next card's snap point, moving the focused card
offscreen. Such a card is now aligned at its own start instead.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
4grayandClaude Opus 5.5 committed 2026-10-03 08:44:55 +02:00
1 parent 31ea629e2e
commit f305e68bec
2 files changed
+25 -1

No files matched your search

@@ -559,6 +559,24 @@ describe('DashboardRailComponent', () => {
});
});
it('keeps a card wider than the visible area at its own start instead of skipping past it', async () => {
// The 1000px viewport cannot hold a 1200px card, so the next
// card's snap point (2420) would move the focused one offscreen.
const { scrollTo, focusLink } = await renderRail({
count: 3,
width: 1200,
stride: 1210,
scrollLeft: 1210,
});
focusLink(1);
expect(scrollTo).toHaveBeenCalledWith({
left: 1210,
behavior: 'auto',
});
});
it('aligns a card cut off on the left with the start edge', async () => {
const { scrollTo, focusLink } = await renderRail({
count: 6,
@@ -318,7 +318,13 @@ export class DashboardRailComponent implements AfterViewInit, OnDestroy {
visible.left;
const maxLeft = track.scrollWidth - track.clientWidth;
let left = maxLeft;
if (hiddenLeft) {
// A card wider than the visible area (a narrow window, or zoom) can
// never fit: show its start rather than a later card's snap point,
// which would move it offscreen.
if (
hiddenLeft ||
rect.right - rect.left > visible.right - visible.left
) {
left = snapOffset(card);
} else {
const needed = track.scrollLeft + rect.right - visible.right;