Review

Restore cellar bin list scroll after bottle detail

Sommeliers at Harbor & Vine scroll thousands of bin rows while pulling wine for service, then open a bottle provenance sheet and hit back. Wire FixedSizeList so the bin rail remembers its scrollOffset in sessionStorage and remounts at that offset, so they land on the same rack section instead of jumping to the top of the cellar list.

react-windowTier 2react-windowscroll-restorenavigationux

Click a line to flag it, pick one or more labels, then submit. If the change looks correct, approve it.

src/features/cellar/BottleBinList.tsx+17-3
11import { useCallback } from "react";
22import { FixedSizeList as List, type ListOnScrollProps } from "react-window";
33import { useNavigate } from "react-router-dom";
44import type { CellarBin } from "@/api/cellar";
55
6+const SCROLL_KEY = "cellar:bin-list-scroll";
7+
68type Props = { bins: CellarBin[] };
79
810export function BottleBinList({ bins }: Props) {
911 const navigate = useNavigate();
12+ const initialOffset = Number(sessionStorage.getItem(SCROLL_KEY) ?? 0);
13+
14+ const onScroll = useCallback(({ scrollOffset }: ListOnScrollProps) => {
15+ sessionStorage.setItem(SCROLL_KEY, String(scrollOffset));
16+ }, []);
1017
1118 const Row = ({ index, style }: { index: number; style: React.CSSProperties }) => {
1219 const bin = bins[index]!;
1320 return (
1421 <button type="button" style={style} onClick={() => navigate(`/cellar/bins/${bin.id}`)}>
1522 <span className="bin-code">{bin.rack}-{bin.slot}</span>
1623 <span className="bin-label">{bin.producer} · {bin.vintage}</span>
1724 </button>
1825 );
1926 };
2027
2128 return (
22- <List height={720} width="100%" itemCount={bins.length} itemSize={52}>
23- {Row}
24- </List>
29+ <List
30+ height={720}
31+ width="100%"
32+ itemCount={bins.length}
33+ itemSize={52}
34+ initialScrollOffset={Number.isFinite(initialOffset) ? initialOffset : 0}
35+ onScroll={onScroll}
36+ >
37+ {Row}
38+ </List>
2539 );
2640}