fix(feed): drop the compact row's columns by the ROW's width, not the viewport

The viewport was the wrong signal: the nav rail and filter panel move the
row's width by ~430px between them, so at a 1280 window with both pinned
every column still qualified while the row had 762px for 766px of them —
the title squeezed back to nothing, the exact bug the breakpoints were
meant to fix. My own comment predicted it and I didn't follow it through.

VirtualFeed already measures the container for colCount, so it now passes
the item's real width down. Measured in the failing config: title -4 ->
359 with the date column standing down.
This commit is contained in:
2026-07-17 02:11:06 +02:00
parent 21cc5de034
commit be05c80d82
2 changed files with 44 additions and 18 deletions
+14 -1
View File
@@ -86,6 +86,12 @@ export default function VirtualFeed({
// Distance from the scroll element's content top to where this list starts (the
// feed toolbar sits above it inside the same scroll area).
const [scrollMargin, setScrollMargin] = useState(0);
// How wide ONE row/card actually renders. The one-line row drops columns as this shrinks, and it
// has to be the real width, not the viewport: the nav rail (56 slim / ~230 pinned) and the filter
// panel (~80 tab / ~256 pinned) move it by ~430px between them. A viewport breakpoint got this
// wrong — at 1280 with both pinned every column still showed while the row had 762px for 766px of
// them, which squeezed the title to nothing. This is measured here anyway, for colCount.
const [itemWidth, setItemWidth] = useState(0);
useLayoutEffect(() => {
if (listRef.current) setScrollEl(getScrollParent(listRef.current));
@@ -103,7 +109,13 @@ export default function VirtualFeed({
scrollEl.scrollTop;
setScrollMargin(m);
}
setColCount(columnsFor(view, node.clientWidth));
const w = node.clientWidth;
const cols = columnsFor(view, w);
setColCount(cols);
const { minCol: min, maxCol: max } = FEED_VIEW_SPEC[view];
setItemWidth(
min == null ? Math.min(w, max ?? w) : Math.floor((w - GRID_GAP * (cols - 1)) / cols)
);
};
measure();
const ro = new ResizeObserver(measure);
@@ -168,6 +180,7 @@ export default function VirtualFeed({
key={v.id}
video={v}
view={view}
width={itemWidth}
onState={onState}
onToggleSave={onToggleSave}
onOpenChannel={onOpenChannel}