@@ -15,6 +15,8 @@ type PopoverState = {
1515 left : number ;
1616 top : number ;
1717 anchorLeft : number ;
18+ anchorTop : number ;
19+ anchorBottom : number ;
1820} ;
1921
2022const items : Item [ ] = [
@@ -129,19 +131,46 @@ function App() {
129131
130132 const shellRect = frameShell . getBoundingClientRect ( ) ;
131133 const popoverWidth = node . offsetWidth ;
134+ const popoverHeight = node . offsetHeight ;
132135 const viewportPadding = 8 ;
136+
133137 const minLeft = Math . max ( viewportPadding - shellRect . left , 8 ) ;
134138 const maxLeft = Math . max (
135139 minLeft ,
136140 window . innerWidth - viewportPadding - shellRect . left - popoverWidth
137141 ) ;
138142 const nextLeft = Math . min ( Math . max ( popover . anchorLeft , minLeft ) , maxLeft ) ;
139143
144+ const spaceBelow =
145+ window . innerHeight - shellRect . top - popover . anchorBottom ;
146+ const canPlaceBelow = spaceBelow >= popoverHeight + 10 ;
147+
148+ const preferredTop = canPlaceBelow
149+ ? popover . anchorBottom + 10
150+ : Math . max (
151+ viewportPadding - shellRect . top ,
152+ popover . anchorTop - popoverHeight - 10
153+ ) ;
154+
155+ const maxTop = Math . max (
156+ viewportPadding - shellRect . top ,
157+ window . innerHeight - viewportPadding - shellRect . top - popoverHeight
158+ ) ;
159+
160+ const nextTop = Math . min ( preferredTop , maxTop ) ;
161+
140162 setPopover ( ( current ) => {
141- if ( ! current || current . left === nextLeft ) return current ;
163+ if (
164+ ! current ||
165+ ( current . left === nextLeft && current . top === nextTop )
166+ ) {
167+ return current ;
168+ }
169+
142170 return {
143171 ...current ,
144172 left : nextLeft ,
173+ top : nextTop ,
145174 } ;
146175 } ) ;
147176 } ;
@@ -183,8 +212,10 @@ function App() {
183212 return {
184213 hiddenItems : args . hiddenItems ,
185214 left : anchorLeft ,
186- anchorLeft,
187215 top : triggerRect . bottom - frameRect . top + 10 ,
216+ anchorLeft,
217+ anchorTop : triggerRect . top - frameRect . top ,
218+ anchorBottom : triggerRect . bottom - frameRect . top ,
188219 } ;
189220 } ) ;
190221 } ;
@@ -270,7 +301,10 @@ function App() {
270301 className = "example-frame"
271302 style = { {
272303 width : isMobileViewport
273- ? `min(100%, ${ Math . min ( mobileFrameWidth , mobileSliderMax ) } px)`
304+ ? `min(100%, ${ Math . min (
305+ mobileFrameWidth ,
306+ mobileSliderMax
307+ ) } px)`
274308 : "min(100%, 360px)" ,
275309 } }
276310 >
0 commit comments