mui / mui/base-ui

[Positioner] Not all `sticky` and `positionMethod` combos make sense

Open
#1,207 1 comment 0 reactions 0 assignees View on GitHub
breaking change component: menu component: popover
Dominant language
TypeScript
Stars
10.9k
Forks
543
Avg merge
1d 20h
Merged PRs (30d)
101

Description

Finally got to test `sticky` and `positionMethod` options thoroughly:

https://p8xtr7.csb.app/
https://codesandbox.io/p/sandbox/postion-method-sticky-combos-p8xtr7

Testing in Safari on a M1 Pro device:

| Props | static container | fixed container |
| ---------------------------------------- | ---------------- | --------------- |
| positionMethod="absolute" sticky={false} | Perfect | Skips frames badly |
| positionMethod="absolute" sticky={true} | Skips frames badly | Skips frames badly |
| positionMethod="fixed" sticky={false} | Skips frames mildly | Perfect* |
| positionMethod="fixed" sticky={true} | Skips frames mildly | Perfect* |

\* Note: in fixed containers, `sticky` value has no effect

https://github.com/user-attachments/assets/b3ad8d68-086c-48bf-9791-9db4d816b0aa

Chrome is better, as it skips fewer frames (but exactly in the same ways).
Firefox is similar/worse.

Effectively, there seems to be two combinations that make sense:
- positionMethod="absolute" sticky={false}
- Works great in a static container
- positionMethod="fixed" sticky={true}
- Works great in a fixed container
- Works OK in a static container to achieve a sticky positioner

Am I missing the use cases for the rest?
- positionMethod="fixed" sticky={false}
- In static containers: just like `positionMethod="absolute" sticky={false}`, but worse because it can skip frames
- In fixed containers: exactly like `positionMethod="fixed" sticky={true}`
- positionMethod="absolute" sticky={true}
- In static containers: skips frames when running up the edge
- In fixed containers: skips frames all the time

If not missing any use cases, it looks like this API can be reduced to a single boolean prop or a single string prop with two values.

***

One more thing to consider is that it might be viable to implement a different positioning strategy for a better sticky popup experience in a static container: use position absolute while the element is attached to the trigger and switch to position fixed when it attaches to the edge of the viewport. This way, the only opportunity to skip frames would be during the position change, and not during the rest of the scroll events.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.