Skip to content

Commit

Permalink
feat: react-window for long lists (MenuDropdown) (#789)
Browse files Browse the repository at this point in the history
  • Loading branch information
ChitlangeSahas authored Jun 30, 2022
1 parent 555f954 commit e550a12
Show file tree
Hide file tree
Showing 5 changed files with 101 additions and 33 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Changelog

### 4.7.0 (2022-06-30)

- [789](https://github.com/influxdata/clockface/pull/789): react-window for long lists in MenuDropdown component

### 4.6.1 (2022-06-25)

- [786](https://github.com/influxdata/clockface/pull/786): MenuDropdown component design fixes
Expand Down
6 changes: 5 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@influxdata/clockface",
"version": "4.6.1",
"version": "4.7.0",
"license": "MIT",
"main": "dist/index.js",
"style": "dist/index.css",
Expand Down Expand Up @@ -112,5 +112,9 @@
"jest/**/ansi-regex": "^3.0.1",
"eslint/**/ansi-regex": "^4.1.1",
"@wessberg/**/browserslist": "^4.16.5"
},
"dependencies": {
"@types/react-window": "^1.8.5",
"react-window": "^1.8.7"
}
}
44 changes: 16 additions & 28 deletions src/Components/Dropdowns/Composed/MenuDropdown.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ import React, {
useRef,
useState,
} from 'react'
import classnames from 'classnames'
import {MenuStatus} from '../Dropdown'
import {FixedSizeList as List} from 'react-window'

// Components
import {Dropdown} from '../.'
Expand All @@ -24,6 +24,7 @@ import {
IconFont,
StandardFunctionProps,
} from '../../../Types'
import classnames from 'classnames'

export interface MenuItem {
name: string
Expand Down Expand Up @@ -51,10 +52,6 @@ export interface MenuDropdownProps extends StandardFunctionProps {
menuHeaderIcon?: IconFont
/** Text to display in the main menu header */
menuHeaderText?: string
/**enables forced searching once dropdown list exceeds largeListSearch value */
largeListSearch?: boolean
/**the number of total items in the dropdown list before search is forced */
largeListCeiling?: number
/** Text to display by default in the type ahead input */
searchText?: string
/** Optional size of button */
Expand Down Expand Up @@ -96,8 +93,6 @@ export const MenuDropdown: FC<MenuDropdownProps> = ({
defaultText = 'No Account Selected',
menuHeaderIcon = IconFont.Switch_New,
menuHeaderText = 'Switch Account',
largeListCeiling = 0,
largeListSearch = false,
searchText = 'Search Accounts',
menuTheme = DropdownMenuTheme.None,
className,
Expand Down Expand Up @@ -126,9 +121,6 @@ export const MenuDropdown: FC<MenuDropdownProps> = ({

const backupValue = useRef<string>(initialTypedValue)

const largeListValidation =
largeListSearch && queryResults.length > largeListCeiling

useEffect(() => {
if (typedValue.length > 0) {
const result = subMenuOptions.filter(val => {
Expand Down Expand Up @@ -306,10 +298,6 @@ export const MenuDropdown: FC<MenuDropdownProps> = ({
className="cf-dropdown-menu--caret-icon cf-button-icon"
/>
)
const largeListValidationText =
typedValue.length >= 1
? 'There are still too many results. Please input more characters.'
: 'Please input a character to start seeing results.'
const inputComponent = (
<Input
placeholder={searchText}
Expand All @@ -333,24 +321,23 @@ export const MenuDropdown: FC<MenuDropdownProps> = ({
{textEl}
</div>
{inputComponent}
{largeListValidation ? (
<Dropdown.Item
key="nada-no-values-in-filter"
testID="nothing-in-filter-typeAhead"
disabled={true}
wrapText={true}
>
{largeListValidationText}
</Dropdown.Item>
) : (
queryResults?.map((value, index) => {
<List
className="List"
height={150}
itemCount={queryResults.length}
itemSize={50}
width={'300px'}
itemData={queryResults}
>
{({data, index, style}) => {
const value = data[index]
// add the 'active' class to highlight when arrowing; like a hover
const classN = classnames('menu-dropdown-typeahead-item', {
active: index === selectIndex,
})

return (
<div key={value.id}>
<div key={value.id} style={style}>
<Dropdown.Item
id={value.id}
value={value}
Expand All @@ -366,8 +353,9 @@ export const MenuDropdown: FC<MenuDropdownProps> = ({
)}
</div>
)
})
)}
}}
</List>

{!queryResults || queryResults.length === 0 ? (
<Dropdown.Item
key="nada-no-values-in-filter"
Expand Down
63 changes: 60 additions & 3 deletions src/Components/Dropdowns/Documentation/Dropdowns.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ import {
MultiSelectDropdown,
MultiSelectDropdownRef,
} from '../Composed/MultiSelectDropdown'
import {MenuDropdown} from '../Composed/MenuDropdown'
import {MenuDropdown, SubMenuItem} from '../Composed/MenuDropdown'
import {ColorPreview} from '../../ColorPicker/ColorPreview'

import {TypeAheadDropDown, SelectableItem} from '../Composed/TypeAheadDropDown'
Expand Down Expand Up @@ -67,6 +67,7 @@ import MultiSelectDropdownReadme from './MultiSelectDropdown.md'
import MenuDropdownReadme from './MenuDropdown.md'
import {useState} from '@storybook/addons'
import {FlexBox} from '../../FlexBox'
import {range} from 'lodash'

const dropdownFamilyStories = storiesOf(
'Components/Dropdowns/Family',
Expand Down Expand Up @@ -942,8 +943,64 @@ dropdownComposedStories.add(
selectedOption={selectedOption}
style={object('style', menuDropdownStyle)}
menuStyle={object('menuStyle', menuDropdownMenuStyle)}
largeListSearch={boolean('largeListSearch', false)}
largeListCeiling={number('largeListCeiling', 0)}
options={defaultHrefOptions}
subMenuOptions={typeAheadOptions}
menuHeaderIcon={IconFont.Switch_New}
menuHeaderText={'Switch Account'}
/>
</div>
)
},
{
readme: {
content: marked(MenuDropdownReadme),
},
}
)

dropdownComposedStories.add(
'MenuDropdownStressTest',
() => {
const defaultHrefOptions = [
{
name: 'Settings',
iconFont: IconFont.CogOutline,
href: '/settings',
},
{
name: 'Members',
iconFont: IconFont.UserOutline_New,
href: '/members',
},
{
name: 'Billing',
iconFont: IconFont.Bill,
href: '/billing',
},
]

const typeAheadOptions = range(1, 100000).map(value => {
return {
name: value.toString(),
id: value.toString(),
} as SubMenuItem
})

const selectedOption = {
name: 'EdgeDelta',
id: '1',
}

const menuDropdownStyle = {width: '150px'}

const menuDropdownMenuStyle = {width: '250px'}

return (
<div className="story--example">
<MenuDropdown
selectedOption={selectedOption}
style={object('style', menuDropdownStyle)}
menuStyle={object('menuStyle', menuDropdownMenuStyle)}
options={defaultHrefOptions}
subMenuOptions={typeAheadOptions}
menuHeaderIcon={IconFont.Switch_New}
Expand Down
17 changes: 16 additions & 1 deletion yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2712,6 +2712,13 @@
dependencies:
"@types/react" "*"

"@types/react-window@^1.8.5":
version "1.8.5"
resolved "https://registry.yarnpkg.com/@types/react-window/-/react-window-1.8.5.tgz#285fcc5cea703eef78d90f499e1457e9b5c02fc1"
integrity sha512-V9q3CvhC9Jk9bWBOysPGaWy/Z0lxYcTXLtLipkt2cnRj1JOSFNF7wqGpkScSXMgBwC+fnVRg/7shwgddBG5ICw==
dependencies:
"@types/react" "*"

"@types/react@*", "@types/react@^17.0.35":
version "17.0.35"
resolved "https://registry.yarnpkg.com/@types/react/-/react-17.0.35.tgz#217164cf830267d56cd1aec09dcf25a541eedd4c"
Expand Down Expand Up @@ -9057,7 +9064,7 @@ memfs@^3.1.2:
dependencies:
fs-monkey "1.0.3"

memoize-one@^5.0.0:
"memoize-one@>=3.1.1 <6", memoize-one@^5.0.0:
version "5.2.1"
resolved "https://registry.yarnpkg.com/memoize-one/-/memoize-one-5.2.1.tgz#8337aa3c4335581839ec01c3d594090cebe8f00e"
integrity sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q==
Expand Down Expand Up @@ -11034,6 +11041,14 @@ react-transition-group@^4.3.0:
loose-envify "^1.4.0"
prop-types "^15.6.2"

react-window@^1.8.7:
version "1.8.7"
resolved "https://registry.yarnpkg.com/react-window/-/react-window-1.8.7.tgz#5e9fd0d23f48f432d7022cdb327219353a15f0d4"
integrity sha512-JHEZbPXBpKMmoNO1bNhoXOOLg/ujhL/BU4IqVU9r8eQPcy5KQnGHIHDRkJ0ns9IM5+Aq5LNwt3j8t3tIrePQzA==
dependencies:
"@babel/runtime" "^7.0.0"
memoize-one ">=3.1.1 <6"

react@^16.8.3:
version "16.14.0"
resolved "https://registry.yarnpkg.com/react/-/react-16.14.0.tgz#94d776ddd0aaa37da3eda8fc5b6b18a4c9a3114d"
Expand Down

0 comments on commit e550a12

Please sign in to comment.