👁️
5
fork

Configure Feed

Select the types of activity you want to include in your feed.

more accurate virtualizer estimate

+25 -1
+25 -1
src/routes/cards/index.tsx
··· 81 81 return columns; 82 82 } 83 83 84 + // Calculate row height from viewport to avoid dynamic measurement (causes scroll stutter on mobile). 85 + // SYNC WARNING: These values must match the grid CSS in the render below: 86 + // - gap-4 = 16px, pb-4 = 16px, px-6 = 24px each side, max-w-7xl = 1280px 87 + // - Cards use aspect-[5/7] 88 + function getRowHeight(columns: number) { 89 + if (typeof window === "undefined") return 300; 90 + 91 + const GAP = 16; 92 + const ROW_PADDING = 16; 93 + const CONTAINER_PADDING = 24 * 2; 94 + const MAX_WIDTH = 1280; 95 + 96 + const viewportWidth = window.innerWidth; 97 + const containerWidth = Math.min(viewportWidth, MAX_WIDTH) - CONTAINER_PADDING; 98 + const totalGapWidth = GAP * (columns - 1); 99 + const cardWidth = (containerWidth - totalGapWidth) / columns; 100 + const cardHeight = cardWidth * (7 / 5); 101 + 102 + return cardHeight + ROW_PADDING; 103 + } 104 + 84 105 const SCROLL_STORAGE_KEY = "cards-scroll-position"; 85 106 86 107 const SORT_OPTIONS: { value: string; label: string; sort: SortOption }[] = [ ··· 148 169 149 170 const rowCount = Math.ceil(totalCount / columns); 150 171 172 + // Use calculated row height to minimize measurement corrections (causes scroll stutter on mobile) 173 + const rowHeight = getRowHeight(columns); 174 + 151 175 const virtualizer = useWindowVirtualizer({ 152 176 count: rowCount, 153 - estimateSize: () => 300, // Initial estimate, measureElement will correct it 177 + estimateSize: () => rowHeight, 154 178 overscan: 2, 155 179 scrollMargin: listRef.current?.offsetTop ?? 0, 156 180 });