11import { TriangleDownIcon } from '@primer/octicons-react'
22import type { Meta } from '@storybook/react-vite'
33import type React from 'react'
4- import { useState } from 'react'
4+ import { useState , useEffect , useRef } from 'react'
55
6- import Box from '../Box'
76import { Button } from '../Button'
87import { SelectPanel } from '.'
98import type { ItemInput } from '../deprecated/ActionList/List'
109import FormControl from '../FormControl'
1110import Text from '../Text'
1211import Select from '../Select/Select'
1312import type { SelectPanelSecondaryAction } from './SelectPanel'
13+ import classes from './SelectPanel.stories.module.css'
1414
1515const meta : Meta < typeof SelectPanel > = {
1616 title : 'Components/SelectPanel/Dev' ,
@@ -30,16 +30,11 @@ const NoResultsMessage = (filter: string): {variant: 'empty'; title: string; bod
3030function getColorCircle ( color : string ) {
3131 return function ( ) {
3232 return (
33- < Box
34- sx = { {
33+ < div
34+ className = { classes . ColorCircle }
35+ style = { {
3536 backgroundColor : color ,
3637 borderColor : color ,
37- width : 14 ,
38- height : 14 ,
39- borderRadius : 10 ,
40- margin : 'auto' ,
41- borderWidth : '1px' ,
42- borderStyle : 'solid' ,
4338 } }
4439 />
4540 )
@@ -113,85 +108,6 @@ export const WithCss = () => {
113108 )
114109}
115110
116- export const WithSx = ( ) => {
117- const [ selected , setSelected ] = useState < ItemInput [ ] > ( items . slice ( 1 , 3 ) )
118- const [ filter , setFilter ] = useState ( '' )
119- const filteredItems = items . filter ( item => item . text ?. toLowerCase ( ) . startsWith ( filter . toLowerCase ( ) ) )
120- // design guidelines say to sort selected items first
121- const selectedItemsSortedFirst = filteredItems . sort ( ( a , b ) => {
122- const aIsSelected = selected . some ( selectedItem => selectedItem . text === a . text )
123- const bIsSelected = selected . some ( selectedItem => selectedItem . text === b . text )
124- if ( aIsSelected && ! bIsSelected ) return - 1
125- if ( ! aIsSelected && bIsSelected ) return 1
126- return 0
127- } )
128- const [ open , setOpen ] = useState ( false )
129-
130- return (
131- < FormControl >
132- < FormControl . Label > Labels</ FormControl . Label >
133- < SelectPanel
134- title = "Select labels"
135- placeholder = "Select labels" // button text when no items are selected
136- subtitle = "Use labels to organize issues and pull requests"
137- renderAnchor = { ( { children, ...anchorProps } ) => (
138- < Button trailingAction = { TriangleDownIcon } { ...anchorProps } aria-haspopup = "dialog" >
139- { children }
140- </ Button >
141- ) }
142- open = { open }
143- onOpenChange = { setOpen }
144- items = { selectedItemsSortedFirst }
145- selected = { selected }
146- onSelectedChange = { setSelected }
147- onFilterChange = { setFilter }
148- sx = { { fontFamily : 'Times New Roman' } }
149- message = { selectedItemsSortedFirst . length === 0 ? NoResultsMessage ( filter ) : undefined }
150- />
151- </ FormControl >
152- )
153- }
154-
155- export const WithSxAndCSS = ( ) => {
156- const [ selected , setSelected ] = useState < ItemInput [ ] > ( items . slice ( 1 , 3 ) )
157- const [ filter , setFilter ] = useState ( '' )
158- const filteredItems = items . filter ( item => item . text ?. toLowerCase ( ) . startsWith ( filter . toLowerCase ( ) ) )
159- // design guidelines say to sort selected items first
160- const selectedItemsSortedFirst = filteredItems . sort ( ( a , b ) => {
161- const aIsSelected = selected . some ( selectedItem => selectedItem . text === a . text )
162- const bIsSelected = selected . some ( selectedItem => selectedItem . text === b . text )
163- if ( aIsSelected && ! bIsSelected ) return - 1
164- if ( ! aIsSelected && bIsSelected ) return 1
165- return 0
166- } )
167- const [ open , setOpen ] = useState ( false )
168-
169- return (
170- < FormControl >
171- < FormControl . Label > Labels</ FormControl . Label >
172- < SelectPanel
173- title = "Select labels"
174- placeholder = "Select labels" // button text when no items are selected
175- subtitle = "Use labels to organize issues and pull requests"
176- renderAnchor = { ( { children, ...anchorProps } ) => (
177- < Button trailingAction = { TriangleDownIcon } { ...anchorProps } aria-haspopup = "dialog" >
178- { children }
179- </ Button >
180- ) }
181- open = { open }
182- onOpenChange = { setOpen }
183- items = { selectedItemsSortedFirst }
184- selected = { selected }
185- onSelectedChange = { setSelected }
186- onFilterChange = { setFilter }
187- sx = { { fontFamily : 'Times New Roman' } }
188- className = "testCustomClassnameMono"
189- message = { selectedItemsSortedFirst . length === 0 ? NoResultsMessage ( filter ) : undefined }
190- />
191- </ FormControl >
192- )
193- }
194-
195111const simpleItems = [
196112 { leadingVisual : getColorCircle ( '#a2eeef' ) , text : 'enhancement' , id : 1 } ,
197113 { leadingVisual : getColorCircle ( '#d73a4a' ) , text : 'bug' , id : 2 } ,
@@ -406,3 +322,66 @@ export const AllVariants = () => {
406322 </ >
407323 )
408324}
325+
326+ const NUMBER_OF_ITEMS = 500
327+ const lotsOfItems = Array . from ( { length : NUMBER_OF_ITEMS } , ( _ , index ) => {
328+ return {
329+ id : index ,
330+ text : `Item ${ index } ` ,
331+ description : `Description ${ index } ` ,
332+ leadingVisual : getColorCircle ( '#a2eeef' ) ,
333+ }
334+ } )
335+
336+ export const LotsOfItems = ( ) => {
337+ const [ selected , setSelected ] = useState < ItemInput [ ] > ( [ ] )
338+ const [ filter , setFilter ] = useState ( '' )
339+ const filteredItems = lotsOfItems . filter ( item => item . text . toLowerCase ( ) . startsWith ( filter . toLowerCase ( ) ) )
340+ const [ open , setOpen ] = useState ( false )
341+ const timeBeforeOpen = useRef < number > ( )
342+ const timeAfterOpen = useRef < number > ( )
343+ const [ timeTakenToOpen , setTimeTakenToOpen ] = useState < number > ( )
344+
345+ const onOpenChange = ( ) => {
346+ timeBeforeOpen . current = performance . now ( )
347+ setOpen ( ! open )
348+ }
349+
350+ useEffect ( ( ) => {
351+ if ( open ) {
352+ timeAfterOpen . current = performance . now ( )
353+ if ( timeBeforeOpen . current ) setTimeTakenToOpen ( timeAfterOpen . current - timeBeforeOpen . current )
354+ }
355+ } , [ open ] )
356+
357+ return (
358+ < >
359+ < p >
360+ Time taken to render { NUMBER_OF_ITEMS } items: { timeTakenToOpen || '(click "Select Labels" to open)' }
361+ </ p >
362+
363+ < FormControl >
364+ < FormControl . Label > Labels</ FormControl . Label >
365+ < SelectPanel
366+ title = "Select labels"
367+ placeholder = "Select labels"
368+ subtitle = "Use labels to organize issues and pull requests"
369+ renderAnchor = { ( { children, ...anchorProps } ) => (
370+ < Button trailingAction = { TriangleDownIcon } { ...anchorProps } aria-haspopup = "dialog" >
371+ { children }
372+ </ Button >
373+ ) }
374+ open = { open }
375+ onOpenChange = { onOpenChange }
376+ items = { filteredItems }
377+ selected = { selected }
378+ onSelectedChange = { setSelected }
379+ onFilterChange = { setFilter }
380+ width = "medium"
381+ height = "large"
382+ message = { filteredItems . length === 0 ? NoResultsMessage ( filter ) : undefined }
383+ />
384+ </ FormControl >
385+ </ >
386+ )
387+ }
0 commit comments