Browse Source

fix(useOverlay): Allow alt axis shift before applying max size (#47849)

Allow overlays to shift along the alt axis before applying the `maxSize`
modifier.

**Before ——** to prevent overflow on the right side, `maxSize`
prematurely constrains the overlay's width, even though there is more
space on the left side and the overlay can shift leftward
<img width="438" alt="image"
src="https://user-images.githubusercontent.com/44172267/234090258-6dd8a705-32ff-4a65-9ffc-4422e841a1b1.png">

**After ——** `maxSize` allows the overlay to shift leftward when there
is space to do that
<img width="438" alt="image"
src="https://user-images.githubusercontent.com/44172267/234090324-925634c7-f919-48e7-930b-5bb10b4b91df.png">

**`maxSize` still works as expected along the main axis:**
<img width="229" alt="image"
src="https://user-images.githubusercontent.com/44172267/234088570-177af119-b896-4912-9289-e4cfcd221b76.png">
Vu Luong 1 year ago
parent
commit
8d8da40473
1 changed files with 20 additions and 10 deletions
  1. 20 10
      static/app/utils/useOverlay.tsx

+ 20 - 10
static/app/utils/useOverlay.tsx

@@ -36,19 +36,21 @@ const maxSize: Modifier<'maxSize', PreventOverflowOptions> = {
     const flippedWidthSide = basePlacement === 'left' ? 'right' : 'left';
     const flippedHeightSide = basePlacement === 'top' ? 'bottom' : 'top';
 
-    // If there is enough space on the other side, then allow the popper to flip
-    // without constraining its size
-    const maxHeight = Math.max(
-      height - overflow[heightSide] - y,
-      -overflow[flippedHeightSide]
-    );
+    const maxHeight = ['left', 'right'].includes(basePlacement)
+      ? // If the main axis is horizontal, then maxHeight = the boundary's height
+        height - overflow.top - overflow.bottom
+      : // Otherwise, set max height unless there is enough space on the other side to
+        // flip the popper to
+        Math.max(height - overflow[heightSide] - y, -overflow[flippedHeightSide]);
 
     // If there is enough space on the other side, then allow the popper to flip
     // without constraining its size
-    const maxWidth = Math.max(
-      width - overflow[widthSide] - x,
-      -overflow[flippedWidthSide]
-    );
+    const maxWidth = ['top', 'bottom'].includes(basePlacement)
+      ? // If the main axis is vertical, then maxWidth = the boundary's width
+        width - overflow.left - overflow.right
+      : // Otherwise, set max width unless there is enough space on the other side to
+        // flip the popper to
+        Math.max(width - overflow[widthSide] - x, -overflow[flippedWidthSide]);
 
     state.modifiersData[name] = {
       width: maxWidth,
@@ -149,6 +151,13 @@ function useOverlay({
           padding: 4,
         },
       },
+      {
+        name: 'flip',
+        options: {
+          // Only flip on main axis
+          flipVariations: false,
+        },
+      },
       {
         name: 'offset',
         options: {
@@ -229,6 +238,7 @@ function useOverlay({
   return {
     isOpen: openState.isOpen,
     state: openState,
+    update: popperUpdate,
     triggerRef,
     triggerProps: {
       ref: setTriggerElement,