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

Dynamic positioning with Floating UI #1852

Open
adamreisnz opened this issue Sep 16, 2024 · 0 comments
Open

Dynamic positioning with Floating UI #1852

adamreisnz opened this issue Sep 16, 2024 · 0 comments

Comments

@adamreisnz
Copy link

adamreisnz commented Sep 16, 2024

Is your feature request related to a problem? Please describe.
The current documentation contains a section with an example for using Popper integration for custom positioning: https://vue-select.org/guide/positioning.html#popper-js-integration

However, Popper.JS has now been replaced by Floating UI, and the API of it is vastly different from Popper.

Describe the solution you'd like
It would be good to have an example in the documentation on how to accomplish custom positioning using Floating UI.

There is currently no practical way to do this, as Floating UI requires a reference to the dropdown element (the floating element). This is currently not accessible through VSelect as far as I can see.

Ideally, VSelect would simply have built in support for positioning itself either below the target element or above, depending on the scroll position, so that we didn't have to rely on an external package to accomplish this.

Describe alternatives you've considered
A quick hacky workaround is to set the reference to the dropdown element in the calculatePosition function and then watch the floatingStyles for changes:

//Refs
const vSelect = ref(null)
const dropdownRef = ref(null)

//Use floating UI
const {floatingStyles} = useFloating(vSelect, dropdownRef, {
  placement,
  middleware: [
    offset(8),
    flip(),
  ],
  whileElementsMounted: autoUpdate,
})

//Calculate position
const calculatePosition = dropdown => {
  dropdownRef.value = dropdown //Remember the dropdown element
  dropdown.style.width = `${vSelect.value.$el.offsetWidth}px` //Using the width provided to `calculatePosition` doesn't work, as it's not the right size.
}

//Update floating styles
watch(floatingStyles, () => {
  if (dropdownRef.value) {
    Object.assign(dropdownRef.value.style, floatingStyles.value)
  }
})

However, this was not ideal as it means now we have to append the dropdown to the body, which means we can no longer apply conditional styles or classes as we have lose the nesting of the dropdown element inside of our wrapper component.

This problem with appendToBody is also described in: #1266

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

1 participant