11'use client'
22
3- import styled from '@emotion/styled '
3+ import { assignInlineVars } from '@vanilla-extract/dynamic '
44import type {
55 ButtonHTMLAttributes ,
66 KeyboardEvent ,
@@ -23,82 +23,21 @@ import {
2323import { Popup } from '../Popup'
2424import { SearchInput } from '../SearchInput'
2525import { Stack } from '../Stack'
26- import { SIZES } from './constants'
2726import { getListItem , searchChildren } from './helpers'
2827import { DisclosureContext , useMenu } from './MenuProvider'
28+ import {
29+ heightAvailableSpace ,
30+ heightMenu ,
31+ menu ,
32+ menuContent ,
33+ menuFooter ,
34+ menuList ,
35+ menuSearchInput ,
36+ } from './styles.css'
2937import type { MenuProps } from './types'
3038
3139const SPACE_DISCLOSURE_POPUP = 24 // in px
3240
33- const StyledPopup = styled ( Popup , {
34- shouldForwardProp : prop => ! [ 'searchable' ] . includes ( prop ) ,
35- } ) < { searchable : boolean } > `
36- background-color: ${ ( { theme } ) =>
37- theme . colors . other . elevation . background . raised } ;
38- box-shadow: ${ ( { theme } ) =>
39- `${ theme . shadows . raised [ 0 ] } , ${ theme . shadows . raised [ 1 ] } ` } ;
40- padding: 0;
41-
42- &[data-has-arrow='true'] {
43- &::after {
44- border-color: ${ ( { theme } ) =>
45- theme . colors . other . elevation . background . raised }
46- transparent transparent transparent;
47- }
48- }
49-
50- min-width: ${ SIZES . small } ;
51- max-width: ${ SIZES . large } ;
52-
53- ${ ( { searchable } ) => ( searchable ? `min-width: 20rem` : null ) } ;
54- padding: ${ ( { theme } ) => `${ theme . space [ '0.25' ] } 0` } ;
55-
56- `
57-
58- const Content = styled ( Stack ) `
59- overflow: auto;
60- `
61-
62- const Footer = styled ( Stack ) `
63- padding: ${ ( { theme } ) => theme . space [ '1' ] } ;
64- `
65-
66- const MenuList = styled ( Stack , {
67- shouldForwardProp : prop => ! [ 'height' , 'heightAvailableSpace' ] . includes ( prop ) ,
68- } ) < { height : string ; heightAvailableSpace : string } > `
69- overflow-y: auto;
70- overflow-x: hidden;
71- max-height: ${ ( { theme, height, heightAvailableSpace } ) =>
72- `calc(min(${ height } , ${ heightAvailableSpace } ) - ${ theme . space [ '0.5' ] } )` } ;
73-
74- &:after,
75- &:before {
76- border: solid transparent;
77- border-width: 9px;
78- content: ' ';
79- height: 0;
80- width: 0;
81- position: absolute;
82- pointer-events: none;
83- }
84-
85- &:after {
86- border-color: transparent;
87- }
88- &:before {
89- border-color: transparent;
90- }
91- background-color: ${ ( { theme } ) =>
92- theme . colors . other . elevation . background . raised } ;
93- color: ${ ( { theme } ) => theme . colors . neutral . text } ;
94- border-radius: ${ ( { theme } ) => theme . radii . default } ;
95- position: relative;
96- `
97-
98- const StyledSearchInput = styled ( SearchInput ) `
99- padding: ${ ( { theme } ) => theme . space [ '1' ] } ;
100- `
101-
10241export const Menu = forwardRef (
10342 (
10443 {
@@ -274,17 +213,16 @@ export const Menu = forwardRef(
274213 } , [ isVisible , portalTarget , disclosureRef , placement , noShrink ] )
275214
276215 return (
277- < StyledPopup
216+ < Popup
278217 align = { align }
279218 aria-label = { ariaLabel }
280- className = { className }
281- data-has-arrow = { hasArrow }
219+ className = { `${ className ? `${ className } ` : '' } ${ menu ( { arrow : hasArrow , searchable } ) } ` }
282220 debounceDelay = { triggerMethod === 'hover' ? 250 : 0 }
283221 dynamicDomRendering = { dynamicDomRendering }
284222 hasArrow = { hasArrow }
285223 hideOnClickOutside
286224 id = { finalId }
287- maxHeight = { maxHeight ?? '30rem ' }
225+ maxHeight = { maxHeight ?? 'fit-content ' }
288226 onClose = { ( ) => {
289227 setIsVisible ( false )
290228 setLocalChild ( null )
@@ -298,38 +236,40 @@ export const Menu = forwardRef(
298236 portalTarget = { portalTarget }
299237 ref = { menuRef }
300238 role = "dialog"
301- searchable = { searchable }
302239 tabIndex = { - 1 }
303240 text = {
304- < MenuList
305- className = { className }
241+ < Stack
242+ className = { ` ${ className ? ` ${ className } ` : '' } ${ menuList } ` }
306243 data-testid = { dataTestId }
307- height = { maxHeight ?? '30rem' }
308- heightAvailableSpace = { popupMaxHeight }
309244 onKeyDown = { handleKeyDown }
310245 onMouseEnter = { ( ) => setShouldBeVisible ( true ) }
311246 onMouseLeave = { ( ) => setShouldBeVisible ( false ) }
312247 role = "menu"
248+ style = { assignInlineVars ( {
249+ [ heightMenu ] : maxHeight ?? '30rem' ,
250+ [ heightAvailableSpace ] : popupMaxHeight ,
251+ } ) }
313252 >
314- < Content ref = { contentRef } >
253+ < Stack className = { menuContent } ref = { contentRef } >
315254 { searchable && typeof children !== 'function' ? (
316- < StyledSearchInput
255+ < SearchInput
256+ className = { menuSearchInput }
317257 onSearch = { onSearch }
318258 ref = { searchInputRef }
319259 size = "small"
320260 />
321261 ) : null }
322262 { finalChild }
323- </ Content >
324- { footer ? < Footer > { footer } </ Footer > : null }
325- </ MenuList >
263+ </ Stack >
264+ { footer ? < Stack className = { menuFooter } > { footer } </ Stack > : null }
265+ </ Stack >
326266 }
327267 visible = { triggerMethod === 'click' ? isVisible : shouldBeVisible }
328268 >
329269 < DisclosureContext . Provider value >
330270 { finalDisclosure }
331271 </ DisclosureContext . Provider >
332- </ StyledPopup >
272+ </ Popup >
333273 )
334274 } ,
335275)
0 commit comments