Skip to content

Commit d799803

Browse files
refactor: simplify VirtualList and Select components (#465)
1 parent 56bb11f commit d799803

File tree

12 files changed

+872
-1519
lines changed

12 files changed

+872
-1519
lines changed

apps/site/src/demos/VirtualListDemo.tsx

Lines changed: 434 additions & 219 deletions
Large diffs are not rendered by default.

packages/blend/lib/components/Menu/Menu.tsx

Lines changed: 4 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -116,13 +116,7 @@ const Menu = ({
116116
enableVirtualScrolling && totalItemCount >= virtualScrollThreshold
117117

118118
const renderVirtualItem = useCallback(
119-
({
120-
item,
121-
}: {
122-
item: VirtualListItem
123-
index: number
124-
style: React.CSSProperties
125-
}) => {
119+
({ item }: { item: VirtualListItem; index: number }) => {
126120
const data = item.data || {}
127121
const { type, label, originalItem, groupId, itemIndex } = data as {
128122
type?: string
@@ -262,28 +256,16 @@ const Menu = ({
262256
>
263257
<VirtualList
264258
items={virtualListItems}
265-
itemHeight={
266-
typeof virtualItemHeight === 'number'
267-
? virtualItemHeight
268-
: 40
269-
}
270-
maxHeight={
259+
height={
271260
(maxHeight || 400) - (enableSearch ? 80 : 20)
272261
}
273-
overscan={virtualOverscan}
274-
dynamicHeight={true}
275-
estimatedItemHeight={
262+
itemHeight={
276263
typeof virtualItemHeight === 'number'
277264
? virtualItemHeight
278265
: 40
279266
}
267+
overscan={virtualOverscan}
280268
renderItem={renderVirtualItem}
281-
style={{
282-
height: 'auto',
283-
maxHeight:
284-
(maxHeight || 400) -
285-
(enableSearch ? 80 : 20),
286-
}}
287269
/>
288270
</Block>
289271
) : (

packages/blend/lib/components/MultiSelect/MobileMultiSelect.tsx

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -317,11 +317,9 @@ const MobileMultiSelect: React.FC<MobileMultiSelectProps> = ({
317317
enableVirtualization = false,
318318
virtualListItemHeight = 56,
319319
virtualListOverscan = 5,
320-
itemsToRender,
321320
onEndReached,
322321
endReachedThreshold,
323322
hasMore,
324-
loadingComponent,
325323
}) => {
326324
const { breakPointLabel } = useBreakpoints(BREAKPOINTS)
327325
const isSmallScreen = breakPointLabel === 'sm'
@@ -508,24 +506,14 @@ const MobileMultiSelect: React.FC<MobileMultiSelectProps> = ({
508506
flattenedItems.length > 0 ? (
509507
<VirtualList
510508
items={flattenedItems}
509+
height={600}
511510
itemHeight={virtualListItemHeight}
512-
maxHeight={600}
513511
overscan={virtualListOverscan}
514-
dynamicHeight={true}
515-
estimatedItemHeight={
516-
virtualListItemHeight
517-
}
518-
itemsToRender={itemsToRender}
519512
onEndReached={onEndReached}
520513
endReachedThreshold={
521514
endReachedThreshold
522515
}
523516
hasMore={hasMore}
524-
loadingComponent={loadingComponent}
525-
style={{
526-
height: 'auto',
527-
maxHeight: 600,
528-
}}
529517
renderItem={({
530518
item: flatItem,
531519
}) => {

packages/blend/lib/components/MultiSelect/MultiSelectMenu.tsx

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -135,11 +135,9 @@ const MultiSelectMenu = ({
135135
enableVirtualization = false,
136136
virtualListItemHeight = 48,
137137
virtualListOverscan = 5,
138-
itemsToRender,
139138
onEndReached,
140139
endReachedThreshold,
141140
hasMore,
142-
loadingComponent,
143141
}: MultiSelectMenuProps) => {
144142
const multiSelectTokens =
145143
useResponsiveTokens<MultiSelectTokensType>('MULTI_SELECT')
@@ -346,20 +344,12 @@ const MultiSelectMenu = ({
346344
>
347345
<VirtualList
348346
items={flattenedItems}
347+
height={(maxMenuHeight || 400) - 80}
349348
itemHeight={virtualListItemHeight}
350-
maxHeight={(maxMenuHeight || 400) - 80}
351349
overscan={virtualListOverscan}
352-
dynamicHeight={true}
353-
estimatedItemHeight={virtualListItemHeight}
354-
itemsToRender={itemsToRender}
355350
onEndReached={onEndReached}
356351
endReachedThreshold={endReachedThreshold}
357352
hasMore={hasMore}
358-
loadingComponent={loadingComponent}
359-
style={{
360-
height: 'auto',
361-
maxHeight: (maxMenuHeight || 400) - 80,
362-
}}
363353
renderItem={({ item: flatItem }) => {
364354
const typed =
365355
flatItem as FlattenedMultiSelectItem

packages/blend/lib/components/SingleSelect/MobileSingleSelect.tsx

Lines changed: 1 addition & 182 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React, { useState, useMemo } from 'react'
1+
import React, { useState } from 'react'
22
import {
33
Drawer,
44
DrawerTrigger,
@@ -27,55 +27,9 @@ import SingleSelectTrigger from './SingleSelectTrigger'
2727
import { TextInput } from '../Inputs/TextInput'
2828
import { TextInputSize } from '../Inputs/TextInput/types'
2929
import { Check } from 'lucide-react'
30-
import VirtualList from '../VirtualList/VirtualList'
31-
import type { VirtualListItem } from '../VirtualList/types'
3230

3331
type MobileSingleSelectProps = SingleSelectProps
3432

35-
type FlattenedMobileItem = VirtualListItem & {
36-
type: 'item' | 'label' | 'separator'
37-
item?: SelectMenuItemType
38-
label?: string
39-
groupId?: number
40-
}
41-
42-
const flattenMobileGroups = (
43-
groups: SelectMenuGroupType[]
44-
): FlattenedMobileItem[] => {
45-
const flattened: FlattenedMobileItem[] = []
46-
let idCounter = 0
47-
48-
groups.forEach((group, groupId) => {
49-
if (group.groupLabel) {
50-
flattened.push({
51-
id: `label-${groupId}`,
52-
type: 'label',
53-
label: group.groupLabel,
54-
groupId,
55-
})
56-
}
57-
58-
group.items.forEach((item) => {
59-
flattened.push({
60-
id: `item-${idCounter++}`,
61-
type: 'item',
62-
item,
63-
groupId,
64-
})
65-
})
66-
67-
if (groupId !== groups.length - 1 && group.showSeparator) {
68-
flattened.push({
69-
id: `separator-${groupId}`,
70-
type: 'separator',
71-
groupId,
72-
})
73-
}
74-
})
75-
76-
return flattened
77-
}
78-
7933
const map = function getValueLabelMap(
8034
groups: SelectMenuGroupType[]
8135
): Record<string, string> {
@@ -261,14 +215,6 @@ const MobileSingleSelect: React.FC<MobileSingleSelectProps> = ({
261215
onBlur,
262216
onFocus,
263217
inline = false,
264-
enableVirtualization = false,
265-
virtualListItemHeight = 56,
266-
virtualListOverscan = 5,
267-
itemsToRender,
268-
onEndReached,
269-
endReachedThreshold,
270-
hasMore,
271-
loadingComponent,
272218
}) => {
273219
const { breakPointLabel } = useBreakpoints(BREAKPOINTS)
274220
const isSmallScreen = breakPointLabel === 'sm'
@@ -280,11 +226,6 @@ const MobileSingleSelect: React.FC<MobileSingleSelectProps> = ({
280226

281227
const filteredItems = filterMenuGroups(items, searchText)
282228

283-
const flattenedItems = useMemo(
284-
() => flattenMobileGroups(filteredItems),
285-
[filteredItems]
286-
)
287-
288229
const isItemSelected = selected.length > 0
289230
const isSmallScreenWithLargeSize =
290231
isSmallScreen && size === SelectMenuSize.LARGE
@@ -422,128 +363,6 @@ const MobileSingleSelect: React.FC<MobileSingleSelectProps> = ({
422363
No results found
423364
</Text>
424365
</Block>
425-
) : enableVirtualization &&
426-
flattenedItems.length > 0 ? (
427-
<VirtualList
428-
items={flattenedItems}
429-
itemHeight={virtualListItemHeight}
430-
containerHeight={
431-
parseInt(
432-
String(
433-
singleSelectTokens
434-
.dropdown
435-
.paddingTop || '16'
436-
)
437-
) * 40
438-
}
439-
overscan={virtualListOverscan}
440-
dynamicHeight={true}
441-
estimatedItemHeight={
442-
virtualListItemHeight
443-
}
444-
itemsToRender={itemsToRender}
445-
onEndReached={onEndReached}
446-
endReachedThreshold={
447-
endReachedThreshold
448-
}
449-
hasMore={hasMore}
450-
loadingComponent={loadingComponent}
451-
renderItem={({
452-
item: flatItem,
453-
}) => {
454-
const typed =
455-
flatItem as FlattenedMobileItem
456-
457-
if (typed.type === 'label') {
458-
return (
459-
<Block
460-
padding={`${singleSelectTokens.dropdown.item.gap} ${singleSelectTokens.dropdown.item.padding}`}
461-
margin={
462-
singleSelectTokens
463-
.dropdown
464-
.item.margin
465-
}
466-
>
467-
<Text
468-
variant="body.sm"
469-
color={
470-
singleSelectTokens
471-
.dropdown
472-
.item
473-
.label
474-
.color
475-
.disabled
476-
}
477-
textTransform="uppercase"
478-
fontSize={
479-
singleSelectTokens
480-
.dropdown
481-
.item
482-
.subLabel
483-
.fontSize
484-
}
485-
>
486-
{typed.label}
487-
</Text>
488-
</Block>
489-
)
490-
}
491-
492-
if (
493-
typed.type === 'separator'
494-
) {
495-
return (
496-
<Block
497-
height={
498-
singleSelectTokens
499-
.dropdown
500-
.seperator
501-
.height
502-
}
503-
backgroundColor={
504-
singleSelectTokens
505-
.dropdown
506-
.seperator
507-
.color
508-
}
509-
margin={
510-
singleSelectTokens
511-
.dropdown
512-
.seperator
513-
.margin
514-
}
515-
/>
516-
)
517-
}
518-
519-
if (
520-
typed.type === 'item' &&
521-
typed.item
522-
) {
523-
const isSelected =
524-
selected ===
525-
typed.item.value
526-
return (
527-
<SingleSelectItem
528-
item={typed.item}
529-
isSelected={
530-
isSelected
531-
}
532-
onSelect={(
533-
value
534-
) => {
535-
onSelect(value)
536-
setDrawerOpen(
537-
false
538-
)
539-
}}
540-
/>
541-
)
542-
}
543-
544-
return null
545-
}}
546-
/>
547366
) : (
548367
<Block
549368
display="flex"

packages/blend/lib/components/SingleSelect/SingleSelect.tsx

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -75,10 +75,9 @@ const SingleSelect = ({
7575
onFocus,
7676
inline = false,
7777
fullWidth = false,
78-
enableVirtualization = false,
78+
enableVirtualization,
7979
virtualListItemHeight,
8080
virtualListOverscan,
81-
itemsToRender,
8281
onEndReached,
8382
endReachedThreshold,
8483
hasMore,
@@ -134,7 +133,6 @@ const SingleSelect = ({
134133
enableVirtualization={enableVirtualization}
135134
virtualListItemHeight={virtualListItemHeight}
136135
virtualListOverscan={virtualListOverscan}
137-
itemsToRender={itemsToRender}
138136
onEndReached={onEndReached}
139137
endReachedThreshold={endReachedThreshold}
140138
hasMore={hasMore}
@@ -204,7 +202,6 @@ const SingleSelect = ({
204202
enableVirtualization={enableVirtualization}
205203
virtualListItemHeight={virtualListItemHeight}
206204
virtualListOverscan={virtualListOverscan}
207-
itemsToRender={itemsToRender}
208205
onEndReached={onEndReached}
209206
endReachedThreshold={endReachedThreshold}
210207
hasMore={hasMore}

0 commit comments

Comments
 (0)