@@ -13,17 +13,13 @@ export const positioner = stylex.create({
1313
1414export const popup = stylex . create ( {
1515 base : {
16- padding : space [ '0.5' ] ,
1716 borderRadius : radiusVars [ '--cl-radius-lg' ] ,
18- gap : space [ '0.5' ] ,
1917 outline : 'none' ,
2018 backgroundColor : colorVars [ '--cl-color-card' ] ,
2119 boxShadow : `0 12px 12px -7px light-dark(oklch(0.2046 0 0 / 12%), transparent),
2220 0 24px 24px -10px light-dark(oklch(0.2046 0 0 / 4%), transparent),
2321 0 0 0 1px light-dark(oklch(0.2046 0 0 / 4%), oklch(1 0 0 / 10%))` ,
2422 color : colorVars [ '--cl-color-card-foreground' ] ,
25- display : 'flex' ,
26- flexDirection : 'column' ,
2723 opacity : {
2824 default : 1 ,
2925 ':is([data-ending-style])' : 0 ,
@@ -48,8 +44,22 @@ export const popup = stylex.create({
4844 // reaches the width it has to truncate at.
4945 maxWidth : 'min(18rem, calc(100vw - 2rem))' ,
5046 minWidth : '12.5rem' ,
51- overflowX : 'visible' ,
52- overflowY : 'auto' ,
47+ } ,
48+ } ) ;
49+
50+ // The popup supplies the chrome and the height cap; this scrolls inside it. They cannot be
51+ // one element: `scrollAreaViewport()` carries a `mask-image` for the fade, and a mask clips
52+ // the element's whole rendering — so on the popup it would eat the background and the drop
53+ // shadow along with the overflowing rows. Same split the Dialog panel makes.
54+ export const viewport = stylex . create ( {
55+ base : {
56+ // The inset belongs to the scrolling box, not the popup: `Menu.Separator` bleeds through it
57+ // with a negative margin, and from inside a viewport that clips its inline axis a bleed past
58+ // the popup's own padding would be cut off instead.
59+ padding : space [ '0.5' ] ,
60+ gap : space [ '0.5' ] ,
61+ display : 'flex' ,
62+ flexDirection : 'column' ,
5363 } ,
5464} ) ;
5565
@@ -70,6 +80,9 @@ export const item = stylex.create({
7080 } ,
7181 cursor : { default : 'pointer' , ':is([data-disabled])' : 'not-allowed' } ,
7282 display : 'flex' ,
83+ // The viewport is a height-capped flex column: without this the rows squash to fit the cap
84+ // instead of overflowing it, and the menu silently loses both its row height and its scroll.
85+ flexShrink : 0 ,
7386 fontFamily : fontFamilyVars [ '--cl-font-family-sans' ] ,
7487 fontSize : typeScaleVars [ '--cl-text-sm-size' ] ,
7588 fontWeight : fontWeightVars [ '--cl-font-medium' ] ,
@@ -83,7 +96,7 @@ export const item = stylex.create({
8396 '@media (prefers-reduced-motion: reduce)' : '0.01ms' ,
8497 } ,
8598 transitionProperty : 'background-color' ,
86- height : space [ '7 ' ] ,
99+ height : space [ '8 ' ] ,
87100 width : '100%' ,
88101 '::before' : {
89102 insetBlock : `calc(-1 * ${ space [ '0.5' ] } )` ,
@@ -130,10 +143,11 @@ export const label = stylex.create({
130143
131144export const separator = stylex . create ( {
132145 base : {
133- // Full-bleed across the popup: cancel the popup 's inline padding.
146+ // Full-bleed across the popup: cancel the viewport 's inline padding.
134147 marginBlock : space [ '0.5' ] ,
135148 marginInline : `calc(-1 * ${ space [ '0.5' ] } )` ,
136149 backgroundColor : colorVars [ '--cl-color-border' ] ,
137150 blockSize : '1px' ,
151+ flexShrink : 0 ,
138152 } ,
139153} ) ;
0 commit comments