atomiks / tippyjs

Tooltip, popover, dropdown, and menu library
https://atomiks.github.io/tippyjs/
MIT License
11.92k stars 520 forks source link

Infinite loop when combining flip with inline positioning #977

Closed hejtmii closed 2 years ago

hejtmii commented 3 years ago

Bug description

The way inlinePositioning and flip (detectOverflow) works may cause an infinite loop despite the fact there is an applicable position to use.

I have a situation where I am rendering a popover dialog pointing to a segment of inline text. I am using inlinePositioning plugin to make the arrow point to the actual text and not to the void:

image

My boundary respects the scrolling container for preventOverflow to not fly off to the wild behind the fold:

image

As the popover is pretty tall (may not fit boundary vertically), I want to allow it to flip even to the side(s):

image

The primary placement is top.

The problem is that inlinePositioning plugin changes the reference rectangle during the operation and it may cause an infinite loop

Here is what I found out during debugging:

image

1) The process starts with a preferred top placement with the topmost reference rectangle - red (from inlinePositioning) but finds out it won't fit there 2) flip tries other positions and finds out that right is fine (based on a wrong red reference rectangle right side) and changes the placement to right 3) inlinePositioning changes the reference rectangle to the orange one 4) Since right is not the preferred placement, flip tries other placements 5) Based on orange reference rectangle, top now fits so flip changes the placement to top 6) inlinePositioning changes the reference rectangle to the top most - red rectangle 7) GOTO 1) - top won't fit and infinite loop continues

Reproduction

Click the "link" in the following CodePen, it should land in an infinite loop described above:

https://codepen.io/kentico_martinh/pen/MWoovXv

atomiks commented 2 years ago

@kenticomartinh have you investigated any ideas for a possible solution? I think 3) not being preferred in the diagram is the key problem, we want it to understand it shouldn't continue from there.