carbon-design-system / carbon

A design system built by IBM
https://www.carbondesignsystem.com
Apache License 2.0
7.74k stars 1.79k forks source link

Floating UI: Allow floating-ui-based positioning without `autoAlign` collision detection #17018

Open tay1orjones opened 1 month ago

tay1orjones commented 1 month ago

Right now to take advantage of the position: fixed strategy used by floating-ui, users must use autoAlign, which includes collision detection.

In theory these two could be separated, allowing consumers to take advantage of the benefits of fixed positioning, most notably avoiding clipping of ancestor elements, without having to use autoAlign collision detection.

Open questions

Examples

wkeese commented 1 month ago

FWIW, the reason I asked for this is that you currently can't specify an alignment and concurrently use position:fixed. I.E. with something like this:

<Tooltip align="bottom" autoAlign>

It will ignore the align=bottom even if there's enough space on the bottom.

How will consumers opt-in to this behavior? Adding another prop is everyone's first thought, but is there a way to do this in a more streamlined way?

That's a great question... I don't have a direct answer but ISTM that we should change the defaults to be:

  1. position:fixed positioning because it usually does what we want (i.e. position the popup correctly without clipping, and without any ARIA issues).
  2. align="top"
  3. repositioning the popup if necessary (due to space constraints)
  4. if app specifiesalign , it shouldn't be ignored unless there are space constraints

I realize that's the opposite of what you said ("opt in"), but it's food for thought.

tay1orjones commented 1 week ago

@wkeese how you describe is how it should be working today.

  1. align is used as the preferred placement
  2. If that doesn't fit, it'll reflow to the opposite placement on the same axis. e.g. bottom -> top
  3. If that doesn't fit, it'll try the opposite axis. e.g. bottom -> top -> left -> right

It will ignore the align=bottom even if there's enough space on the bottom.

That shouldn't be the case, all implementations use the flip middleware:

flip() uses a fallback “no space” strategy. Ensures the preferred placement is kept unless there is no space left.

If you're seeing the opposite, I'm happy to look into it if you could put together a stackblitz repro or steps to repro in storybook. We're planning to ensure this type of thing is working correctly across all the components:

tay1orjones commented 1 week ago

@annawen1 @ariellalgilmore @preetibansalui summarizing our meeting yesterday, the tentative plan we came up with is to add a new feature flag allowing consumers to toggle on "dynamic" floating-ui position: fixed-based styling (without collision detection).

Feature flag value autoAlign value Styling applied Collision detection used?
True True floating-ui 'dynamic' styling yes
True False floating-ui 'dynamic' styling no
False True floating-ui 'dynamic' styling yes
False False default scss styling no

This will also provide us a path to make the "dynamic" styling and/or collision detection on-by-default in the future. It would likely be considered a breaking change though, so we'd have to reserve it for our next major.