-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathWindowScrollList.tsx
More file actions
92 lines (85 loc) · 2.16 KB
/
Copy pathWindowScrollList.tsx
File metadata and controls
92 lines (85 loc) · 2.16 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
import { useWindowVirtualizer } from "@tanstack/react-virtual";
import { useEffect, useRef } from "react";
import { useVirtualTextLayout } from "virtual-text-layout";
type Row = { id: string; title: string; subtitle: string };
const TITLE_FONT = "600 16px Inter";
const TITLE_LINE_HEIGHT = 24;
const SUBTITLE_FONT = "14px Inter";
const SUBTITLE_LINE_HEIGHT = 20;
const ROW_PADDING_Y = 24;
export function WindowScrollList({ items }: { items: Row[] }) {
const listRef = useRef<HTMLDivElement>(null);
const { estimateSize, ready, contentWidth } = useVirtualTextLayout(items, {
fields: [
{
getText: (item) => item.title,
font: TITLE_FONT,
lineHeight: TITLE_LINE_HEIGHT,
},
{
getText: (item) => item.subtitle,
font: SUBTITLE_FONT,
lineHeight: SUBTITLE_LINE_HEIGHT,
},
],
fixedHeight: ROW_PADDING_Y * 2,
containerRef: listRef,
});
const virtualizer = useWindowVirtualizer({
count: ready ? items.length : 0,
estimateSize,
overscan: 5,
});
// Force the virtualizer to recompute row heights when the container width changes,
// otherwise it keeps the sizes it cached from the previous width.
useEffect(() => {
if (contentWidth > 0) virtualizer.measure();
}, [contentWidth, virtualizer]);
return (
<div ref={listRef} style={{ padding: "0 16px" }}>
<div
style={{
height: virtualizer.getTotalSize(),
position: "relative",
width: "100%",
}}
>
{virtualizer.getVirtualItems().map((vi) => {
const item = items[vi.index];
return (
<div
key={item.id}
style={{
position: "absolute",
top: 0,
left: 0,
width: "100%",
transform: `translateY(${vi.start}px)`,
height: vi.size,
padding: `${ROW_PADDING_Y}px 0`,
boxSizing: "border-box",
}}
>
<div
style={{
font: TITLE_FONT,
lineHeight: `${TITLE_LINE_HEIGHT}px`,
}}
>
{item.title}
</div>
<div
style={{
font: SUBTITLE_FONT,
lineHeight: `${SUBTITLE_LINE_HEIGHT}px`,
}}
>
{item.subtitle}
</div>
</div>
);
})}
</div>
</div>
);
}