Skip to content

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Core] Collidables #1440

Closed
atomiks opened this issue Dec 12, 2021 · 14 comments · May be fixed by #2348
Closed

[Core] Collidables #1440

atomiks opened this issue Dec 12, 2021 · 14 comments · May be fixed by #2348
Labels
feature This would be nice to have.

Comments

@atomiks
Copy link
Collaborator

atomiks commented Dec 12, 2021

Expands on #1381

There have been feature requests related to collision detection of other floating elements, not just a surrounding boundaries. To do this it looks like we have to think of boundaries as a polygon with "holes", the holes represent other arbitrary elements to detectOverflow to, not just a surrounding rectangle boundary.

A picture is worth a thousand words:

Screen Shot 2021-12-12 at 7 48 26 pm

The holes represent other elements "eating" into the main boundary.


Right now you can either use padding in the shift/flip modifiers (only works for static things like a sticky header or navbar), or let the floating element overlap those other floating elements with a higher z-index.

@atomiks atomiks added the feature This would be nice to have. label Dec 12, 2021
@atomiks atomiks changed the title Support boundaries with “holes” aka detectOverflow relative to arbitrary elements [Floating UI] Support boundaries with “holes” aka detectOverflow relative to arbitrary elements May 3, 2022
@atomiks atomiks changed the title [Floating UI] Support boundaries with “holes” aka detectOverflow relative to arbitrary elements [Core/DOM] Support boundaries with “holes” aka detectOverflow relative to arbitrary elements May 3, 2022
@KutnerUri
Copy link

Yup I also come across this - some banners or header might have a high z-index, and could cover the tooltip, making bad UX.

Ideally, popper would be "smart" enough to detect all z-index items around it and avoid them. Obviously, this is not practical.

Any best practices?

for example:
Screenshot 2022-04-30 at 2 55 18 PM

@atomiks
Copy link
Collaborator Author

atomiks commented May 17, 2022

The only solution is using padding in flip or shift which takes into account the other positioned element, or if your app is not scrollable and instead has individual scrolling containers (e.g. like a desktop UI), you can use a custom boundary to limit it from overflowing its container, thereby not overflowing other positioned elements.

I think this problem is hard to solve and I'm not sure how to even start on the "holes" thing.

@wlib
Copy link

wlib commented Jun 1, 2022

Maybe I misunderstood the problem, but here are my immediate thoughts:

Ideally, the DOM would provide a document.nodesWithinRect() sort of like document.elementsFromPoint, and then we could just test if there is any intersection of the returned set with the set of nodes that shouldn't be overlapped. Since we don't have this DOM API, the reverse could be done: maintain the set of nodes that shouldn't be overlapped, tracking overlap of their bounding boxes with our target floating element. If any of these tracked nodes are positioned by floating-ui, then that's a little performance shortcut.

I will note that at the point where mutual positioning constraints come into play, this massively expands the scope of this library into something like autolayout.

@atomiks
Copy link
Collaborator Author

atomiks commented Feb 1, 2023

I believe there are two algorithms for this — one easy and one hard.

The easy algorithm is already used to detect a clipping boundary. It would be the area of the visible viewport subtracting "fixed"/"sticky" floating elements that are not controlled by Floating UI, but don't really act like "holes" because they're at the edges of the boundary. These are UI elements like a sticky navbar or sidebar.

The hard algorithm is detecting actual "holes" anywhere inside the boundary, where the holes could be other floating elements controlled by Floating UI itself. Forgot to post this here when I first saw it, but I imagine the hard algorithm would generalize the problem and result in positioning like this:

https://twitter.com/blvdmitry/status/1550042703576055808

@atomiks
Copy link
Collaborator Author

atomiks commented Mar 26, 2023

I decided to actually try to solve this and it took me 1 hour to get this far. I've got some logic working for both flip (which only needs a bool check), and shift (which needs the intersection amounts):

Screen.Recording.2023-03-26.at.8.01.27.pm.mov

There are some remaining problems:

  • shift.crossAxis
  • size
  • The API (maybe detectIntersection) and bundle size constraints
  • Correctly dealing with multiple collidables for a shift (not applicable to the above)
  • Detecting other floating elements where they both need to avoid each other, but one likely shouldn't take precedence over the other, meaning there's a kind of "half" avoidance from both (if there's only two), but it gets far more complicated if there's more, something like a flexbox algorithm if they're all side-by-side...

@FezVrasta
Copy link
Member

Do you think CSS grids could help? We could draw a grid on top of the page and position the cells to cover the holes, then you could position each tooltip in a cell and have it positioned by grid

@atomiks
Copy link
Collaborator Author

atomiks commented Mar 27, 2023

The CSS grid solution sounds interesting, but I don't think it helps with needing to coordinate updates between multiple floating elements when they need to avoid each other. Further, positioning is granular to the pixel, and the grid solution may not be suitable for that.

Right now all floating elements can be updated independently of one another and don't need coordination, so we need some kind of system for that.

@atomiks atomiks changed the title [Core/DOM] Support boundaries with “holes” aka detectOverflow relative to arbitrary elements [Core] Collidables Apr 1, 2023
@atomiks
Copy link
Collaborator Author

atomiks commented Apr 1, 2023

I've split this into two separate issues:

  • Collidables (the demo above demonstrates it, can be shipped soon)
  • Coordination (handling a group of floating elements that need to avoid each other in a flexbox-like way, appears trickier when integrating with the collision detection of the rest of the library). The collidable technique works in a rudimentary way for this already, but the positioning doesn't really look nice compared to coordination. [Core] Coordination #2268

@rbozan
Copy link

rbozan commented Apr 1, 2023

does anyone know of an alternative library that does exactly what's described here in the issue?

my use case would be showing multiple popovers simultaneously without them overlapping, while avoiding certain other elements on the page.

@atomiks
Copy link
Collaborator Author

atomiks commented Apr 2, 2023

@rbozan can you show an example of how the popovers are laid out? Would you prefer them to be laid out like a flexbox (coordination), or can they be arbitrarily positioned, as long as there's no overlapping, where popovers that were opened first (or positioned first) take precedence? The latter (this issue) is likely going to be shipped in a week once I get all the edge cases working correctly.

@rbozan
Copy link

rbozan commented Apr 2, 2023

@rbozan can you show an example of how the popovers are laid out? Would you prefer them to be laid out like a flexbox (coordination), or can they be arbitrarily positioned, as long as there's no overlapping, where popovers that were opened first (or positioned first) take precedence? The latter (this issue) is likely going to be shipped in a week once I get all the edge cases working correctly.

Thanks for the reply. Indeed it would be the latter.

After some research I did choose d3 and their force directed graph but I'll gladly use something simpler for my use case.

@Codigo-Fuentes
Copy link

@atomiks hi 👋 has there been any movement on the collidables feature?

@atomiks
Copy link
Collaborator Author

atomiks commented May 22, 2023

Not really. I think I'll most likely release a basic version of the feature that covers some useful cases, but won't be "complete" (especially including #2268). Can I ask what you're looking to use it for? This will help me understand the popular use cases more.

@tay1orjones
Copy link

One use case that isn't outlined here yet is the new WCAG 2.2 requirement to not obscure elements that receive focus. It would be nice if floating-ui could help us avoid overlaying floating ui elements over elements that currently have focus.

I went into greater detail in #2601 without realizing it's highly related to this here.

@floating-ui floating-ui locked and limited conversation to collaborators Jan 11, 2024
@atomiks atomiks converted this issue into discussion #2715 Jan 11, 2024

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

Labels
feature This would be nice to have.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

7 participants