11import styled from '@emotion/styled'
22import {
3- autoUpdate ,
4- flip ,
5- FloatingFocusManager ,
6- FloatingOverlay ,
7- inner ,
8- offset ,
9- shift ,
10- SideObject ,
11- size ,
12- useClick ,
13- useDismiss ,
14- useFloating ,
15- useInnerOffset ,
16- useInteractions ,
17- useListNavigation ,
18- useRole ,
19- useTypeahead
3+ autoUpdate ,
4+ flip ,
5+ FloatingFocusManager ,
6+ FloatingOverlay ,
7+ inner ,
8+ offset ,
9+ shift ,
10+ SideObject ,
11+ size ,
12+ useClick ,
13+ useDismiss ,
14+ useFloating ,
15+ useInnerOffset ,
16+ useInteractions ,
17+ useListNavigation ,
18+ useRole ,
19+ useTypeahead
2020} from '@floating-ui/react-dom-interactions'
2121import React , {
22- ElementType ,
23- ReactNode ,
24- useEffect ,
25- useLayoutEffect ,
26- useRef ,
27- useState
22+ ElementType ,
23+ ReactNode ,
24+ useEffect ,
25+ useLayoutEffect ,
26+ useRef ,
27+ useState
2828} from 'react'
2929import { PC , PP } from '../types/PolymorphicElementProps'
30- import { cssDisablable } from '../utils/styles'
30+ import { cssClickable , cssDisablable } from '../utils/styles'
31+ import { ListItem } from './$List'
3132
3233interface SelectDisplayProps {
3334 fullWidth : boolean
3435}
3536
3637const SelectDisplay = styled . div < SelectDisplayProps > `
3738 ${ cssDisablable }
39+ ${ cssClickable }
40+ display: inline-block;
3841 font-family: inherit;
3942 height: auto;
4043 line-height: normal;
@@ -47,6 +50,13 @@ const SelectDisplay = styled.div<SelectDisplayProps>`
4750 width: ${ ( { fullWidth } ) => ( fullWidth ? '100%' : 'auto' ) } ;
4851`
4952
53+ const SelectItemsWrapper = styled . div `
54+ background: ${ ( { theme } ) => theme . color . background . page } ;
55+ border: ${ ( { theme } ) => theme . styles . border ( ) } ;
56+ border-radius: 8px;
57+ overflow-y: auto;
58+ `
59+
5060// Adopted from https://codesandbox.io/s/shy-snowflake-kp6479?file=/src/Select.tsx:5939-5954
5161
5262type SelectItemNode = string | { value : string }
@@ -80,8 +90,6 @@ export const Select: PC<'button', SelectProps> = React.forwardRef(
8090 const allowSelectRef = useRef ( false )
8191 const allowMouseUpRef = useRef ( true )
8292 const selectTimeoutRef = useRef < any > ( )
83- const upArrowRef = useRef < HTMLDivElement | null > ( null )
84- const downArrowRef = useRef < HTMLDivElement | null > ( null )
8593
8694 const [ open , setOpen ] = useState ( false )
8795 const [ selectedIndex , setSelectedIndex ] = useState ( 0 )
@@ -114,16 +122,17 @@ export const Select: PC<'button', SelectProps> = React.forwardRef(
114122 offset ( 5 ) ,
115123 ...[
116124 touch
117- ? shift ( { crossAxis : true , padding : 10 } )
118- : flip ( { padding : 10 } ) ,
125+ ? shift ( { crossAxis : true , padding : 8 } )
126+ : flip ( { padding : 8 } ) ,
119127 ] ,
120128 size ( {
121- apply ( { elements, availableHeight } ) {
129+ apply ( { elements, availableHeight, rects } ) {
122130 Object . assign ( elements . floating . style , {
123131 maxHeight : `${ availableHeight } px` ,
132+ width : `${ rects . reference . width } px` ,
124133 } )
125134 } ,
126- padding : 10 ,
135+ padding : 8 ,
127136 } ) ,
128137 ]
129138 : [
@@ -133,7 +142,7 @@ export const Select: PC<'button', SelectProps> = React.forwardRef(
133142 index : selectedIndex ,
134143 offset : innerOffset ,
135144 onFallbackChange : setFallback ,
136- padding : 10 ,
145+ padding : 8 ,
137146 minItemsVisible : touch ? 10 : 4 ,
138147 referenceOverflowThreshold : 20 ,
139148 } ) ,
@@ -184,11 +193,7 @@ export const Select: PC<'button', SelectProps> = React.forwardRef(
184193 useLayoutEffect ( ( ) => {
185194 const onPointerDown = ( e : PointerEvent ) : void => {
186195 const target = e . target as Node
187- if (
188- ! refs . floating . current ?. contains ( target ) &&
189- ! upArrowRef . current ?. contains ( target ) &&
190- ! downArrowRef . current ?. contains ( target )
191- ) {
196+ if ( ! refs . floating . current ?. contains ( target ) ) {
192197 setOpen ( false )
193198 }
194199 }
@@ -255,12 +260,13 @@ export const Select: PC<'button', SelectProps> = React.forwardRef(
255260 { open && (
256261 < FloatingOverlay lockScroll = { ! touch } style = { { zIndex : 1 } } >
257262 < FloatingFocusManager context = { context } preventTabbing >
258- < div
263+ < SelectItemsWrapper
259264 ref = { floating }
260265 style = { {
261266 position : strategy ,
262267 top : y ?? 0 ,
263268 left : x ?? 0 ,
269+ width : fullWidth ? '100%' : undefined ,
264270 } }
265271 { ...getFloatingProps ( {
266272 onKeyDown ( ) {
@@ -276,7 +282,8 @@ export const Select: PC<'button', SelectProps> = React.forwardRef(
276282 >
277283 { items . map ( ( item , i ) => {
278284 return (
279- < div
285+ < ListItem < 'div' >
286+ clickable
280287 key = { typeof item === 'string' ? item : item . value }
281288 role = "option"
282289 tabIndex = { 0 }
@@ -300,8 +307,12 @@ export const Select: PC<'button', SelectProps> = React.forwardRef(
300307 allowSelectRef . current = true
301308 allowMouseUpRef . current = false
302309 } ,
303- onKeyDown ( ) {
310+ onKeyDown ( e ) {
304311 allowSelectRef . current = true
312+ if ( e . key === 'Enter' && allowSelectRef . current ) {
313+ setSelectedIndex ( i )
314+ setOpen ( false )
315+ }
305316 } ,
306317 onClick ( ) {
307318 if ( allowSelectRef . current ) {
@@ -327,10 +338,10 @@ export const Select: PC<'button', SelectProps> = React.forwardRef(
327338 } ) }
328339 >
329340 { render ( item ) }
330- </ div >
341+ </ ListItem >
331342 )
332343 } ) }
333- </ div >
344+ </ SelectItemsWrapper >
334345 </ FloatingFocusManager >
335346 </ FloatingOverlay >
336347 ) }
0 commit comments