Skip to content
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

Flip Modifiers Not Applied #749

Open
athielen2 opened this issue Dec 9, 2019 · 8 comments
Open

Flip Modifiers Not Applied #749

athielen2 opened this issue Dec 9, 2019 · 8 comments

Comments

@athielen2
Copy link

athielen2 commented Dec 9, 2019

Describe the bug

When passing popperConfig into an Overlay component, the flip modifiers are not applied.

To Reproduce

Steps to reproduce the behavior:

  1. Create an Overlay component with a popperConfig that has flip modifiers set
  2. Observe that those modifiers are not applied

Expected behavior

Expected that the modifiers passed in (ex: behavior) would be applied to the underlying popper instance

Screenshots

If applicable, add screenshots to help explain your problem.

Environment (please complete the following information)

  • Operating System: [e.g. macOS]
    MacOS
  • Browser, Version [e.g. Chrome 74]
    Chrome 78.0.3904.108
  • react-overlays Version [e.g. 2.0.0]
    2.1.0

Additional context

I see in Overlay.js that the preventOverflow modifiers are spread onto the popper config. Is this intentional?

const { styles, arrowStyles, ...popper } = usePopper(target, rootElement, {
    ...popperConfig,
    placement: placement || 'bottom',
    enableEvents: props.show,
    modifiers: {
      ...modifiers,
      preventOverflow: {
        padding: containerPadding || 5,
        ...modifiers.preventOverflow,
      },
      arrow: {
        ...modifiers.arrow,
        enabled: !!arrowElement,
        element: arrowElement,
      },
      flip: {
        enabled: !!flip,
        ...modifiers.preventOverflow,
      },
    },
  });
@taion
Copy link
Member

taion commented Dec 9, 2019

@jquense should explicitly-specified popperConfig take precedence over our inferred options here?

@juliusv
Copy link

juliusv commented Mar 3, 2020

I've been running into something similar, where the positionFixed: true / strategy: 'fixed' popper config option is ignored, and thus I cannot get a dropdown menu to break out of its scroll container. The reason is that not all popper options are passed on, but are computed like this from just the modifiers property of the provided popper options:

const modifiers = toModifierMap(popperConfig.modifiers);
const popper = usePopper(toggleElement, menuElement, {
placement,
enabled: !!(shouldUsePopper && show),
modifiers: {
...modifiers,
eventListeners: {
enabled: !!show,
},
arrow: {
...modifiers.arrow,
enabled: !!arrowElement,
options: {
...modifiers.arrow?.options,
element: arrowElement,
},
},
flip: {
enabled: !!flip,
...modifiers.flip,
},
},
});

Although this docstring falsely claims that all provided options are passed on:

/**
* A set of popper options and props passed directly to react-popper's Popper component.
*/
popperConfig: PropTypes.object,

@jquense
Copy link
Member

jquense commented Mar 3, 2020

which options aren't being passed?

@juliusv
Copy link

juliusv commented Mar 3, 2020

@jquense Anything outside of the modifiers aren't passed to Popper, but there might be relevant non-modifier options too, like in my case the positionFixed: true (which is parallel to modifiers as a top-level key in popperConfig, not nested inside it). If I manually hack this file to add positionFixed: true in the object passed to usePopper(), my dropdown breaks out correctly.

@jquense
Copy link
Member

jquense commented Mar 4, 2020

Happy to take a PR fixing this if you want to send one over

@juliusv
Copy link

juliusv commented Mar 4, 2020

@jquense I'm afraid I'm lacking a bit of JS testing expertise (naively getting the computed style of the menu and checking for the value of the position attribute yielded me an empty value, so I couldn't get the test to work), but the actual non-code fix itself should just be:

diff --git a/src/DropdownMenu.js b/src/DropdownMenu.js
index ae98e2e..8c2dfbe 100644
--- a/src/DropdownMenu.js
+++ b/src/DropdownMenu.js
@@ -42,6 +42,7 @@ export function useDropdownMenu(options = {}) {
   const modifiers = toModifierMap(popperConfig.modifiers);
 
   const popper = usePopper(toggleElement, menuElement, {
+    ...popperConfig,
     placement,
     enabled: !!(shouldUsePopper && show),
     modifiers: {

For now I switched back to Reactstrap (where this behavior can be made to work), but maybe someone else feels qualified to also add working tests here.

@jquense
Copy link
Member

jquense commented Mar 4, 2020

that change looks fine, i don't think you need to add any tests for it

@juliusv
Copy link

juliusv commented Mar 4, 2020

@jquense Ok great, I filed #779, but didn't mark it as fixing this specific issue here, as the flip modifier still gets overridden after the spread of the user-provided options. Or maybe the spreading order should be inverted, so that for both modifiers and the rest of the popper config, the user-provided values always win? But for now I only provided the obvious (least risky) fix in the PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants