@@ -1357,7 +1357,37 @@ function RemoteFunctions(config) {
13571357 leftPos = offset . left ;
13581358
13591359 if ( elemBounds . top - boxDimensions . height < 6 ) {
1360- topPos = offset . top + elemBounds . height + 6 ;
1360+ // check if placing the box below would cause viewport height increase
1361+ // we need this or else it might cause a flickering issue
1362+ // read this to know why flickering occurs:
1363+ // when we hover over the bottom part of a tall element, the info box appears below it.
1364+ // this increases the live preview height, which makes the cursor position relatively
1365+ // higher due to content shift. the cursor then moves out of the element boundary,
1366+ // ending the hover state. this makes the info box disappear, decreasing the height
1367+ // back, causing the cursor to fall back into the element, restarting the hover cycle.
1368+ // this creates a continuous flickering loop.
1369+ const bottomPosition = offset . top + elemBounds . height + 6 ;
1370+ const wouldIncreaseViewportHeight = bottomPosition + boxDimensions . height > window . innerHeight ;
1371+
1372+ // we only need to use floating position during hover mode (not on click mode)
1373+ const isHoverMode = shouldShowHighlightOnHover ( ) ;
1374+ const shouldUseFloatingPosition = wouldIncreaseViewportHeight && isHoverMode ;
1375+
1376+ if ( shouldUseFloatingPosition ) {
1377+ // float over element at bottom-right to prevent layout shift during hover
1378+ topPos = offset . top + elemBounds . height - boxDimensions . height - 6 ;
1379+ leftPos = offset . left + elemBounds . width - boxDimensions . width ;
1380+
1381+ // make sure it doesn't go off-screen
1382+ if ( leftPos < 0 ) {
1383+ leftPos = offset . left ; // align to left edge of element
1384+ }
1385+ if ( topPos < 0 ) {
1386+ topPos = offset . top + 6 ; // for the top of element
1387+ }
1388+ } else {
1389+ topPos = bottomPosition ;
1390+ }
13611391 }
13621392
13631393 // Check if the box would go off the right of the viewport
0 commit comments