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
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
import * as React from 'react'
import VirtualList, { ItemStyle, ScrollAlignment, ScrollDirection } from '../src'

import { Title, Subtitle, Primary, Stories } from '@storybook/addon-docs/blocks'

export default {
  title: 'VirtualList',
  parameters: {
    docs: {
      page: () => (
        <>
          <Title />
          <Subtitle />
          <Primary />
          <Stories />
        </>
      ),
    },
  },
}

const STICKY_INDICES = [0, 5, 8, 15, 30, 50, 100, 200]
const ITEM_HEIGHT = 48
const ITEM_STYLE: React.CSSProperties = {
  padding: '12px 20px',
  boxSizing: 'border-box',
  fontFamily: 'system-ui, "Helvetica Neue", Helvetica, sans-serif',
  fontSize: '16px',
  lineHeight: '24px',
}

const renderItem = ({ style, index }: { style: ItemStyle; index: number }) => {
  const isSticky = STICKY_INDICES.includes(index)
  const itemStyle = isSticky ? { ...style, ...ITEM_STYLE, backgroundColor: '#f7f7f7' } : { ...style, ...ITEM_STYLE }
  return (
    <div style={itemStyle} key={index}>
      Row #{index} {isSticky ? '(Sticky)' : ''}
    </div>
  )
}

export const Default = () => ( <div style={{ border: '3px solid #edeff0' }}> <VirtualList width="auto" height={400} itemCount={1000} renderItem={renderItem} itemSize={ITEM_HEIGHT} stickyIndices={STICKY_INDICES} scrollDirection={ScrollDirection.VERTICAL} overscanCount={5} /> </div> )
export const Controlled = () => { const [index, setIndex] = React.useState<number | null>(null) const setNewIndex = React.useCallback(index => { setIndex(null) setTimeout(() => setIndex(index)) }, []) return ( <> <div style={{ marginBottom: 16 }}> <button onClick={() => setNewIndex(5)}>Scroll to 5</button> &nbsp; <button onClick={() => setNewIndex(15)}>Scroll to 15</button> &nbsp; <button onClick={() => setNewIndex(30)}>Scroll to 30</button> </div> <div style={{ border: '3px solid #edeff0' }}> <VirtualList width="auto" height={400} itemCount={1000} renderItem={renderItem} itemSize={ITEM_HEIGHT} stickyIndices={STICKY_INDICES} scrollToIndex={index !== null ? index : undefined} scrollDirection={ScrollDirection.VERTICAL} overscanCount={5} /> </div> </> ) } export const Smart = () => { const [index, setIndex] = React.useState<number | null>(null) const setNewIndex = React.useCallback(index => { setIndex(null) setTimeout(() => setIndex(index)) }, []) return ( <> <div style={{ marginBottom: 16 }}> <button onClick={() => setNewIndex(5)}>Scroll to 5</button> &nbsp; <button onClick={() => setNewIndex(15)}>Scroll to 15</button> &nbsp; <button onClick={() => setNewIndex(30)}>Scroll to 30</button> </div> <div style={{ border: '3px solid #edeff0' }}> <VirtualList width="auto" height={400} itemCount={1000} renderItem={renderItem} itemSize={ITEM_HEIGHT} stickyIndices={STICKY_INDICES} scrollToIndex={index !== null ? index : undefined} scrollDirection={ScrollDirection.VERTICAL} scrollToAlignment={ScrollAlignment.SMART} overscanCount={5} /> </div> </> ) }