fedorovvvv / svelte-floating-ui

Svelte✨ Floating UI 🎈
MIT License
151 stars 8 forks source link

Does not work properly with svelte-portal #4

Closed knpwrs closed 2 years ago

knpwrs commented 2 years ago

When attempting to use svelte-floating-ui with svelte-portal the floating element initially renders in the wrong position. Resizing the window or closing and opening the floating UI fixes it (at least, closing and opening controlled by display: none/block;). If I were to make an educated guess I would say that the floating ui calcualtions are being done before the floating element is moved to the portal.

Here is some example code:

<script lang="ts">
  import Portal from 'svelte-portal';
  import { offset, flip, shift } from '@floating-ui/dom';
  import { createFloatingActions } from 'svelte-floating-ui';

  const [floatingRef, floatingContent] = createFloatingActions({
    strategy: 'absolute',
    placement: 'bottom-end',
    middleware: [offset(6), flip(), shift()],
  });

  const ariaMenuButtonId = 'menu-button';
  const ariaMenuId = 'menu';
  let open = false;
</script>

<button
  id={ariaMenuButtonId}
  type="submit"
  class="h-10 rounded-sm"
  aria-haspopup="true"
  aria-controls={ariaMenuId}
  on:click={() => {
    open = !open;
  }}
  use:floatingRef>Open</button
>

<Portal>
  <ul
    id={ariaMenuId}
    role="menu"
    aria-labelledby={ariaMenuButtonId}
    class="menu w-20"
    class:menu-open={open}
    use:floatingContent
  >
    <li role="none"><a href="/#" role="menuitem">Menu Item</a></li>
  </ul>
</Portal>

<style>
  .menu {
    display: none;
  }

  .menu-open {
    display: block;
  }
</style>
knpwrs commented 2 years ago

This appears to work:

6c6
<   const [floatingRef, floatingContent] = createFloatingActions({
---
>   const [floatingRef, floatingContent, updatePosition] = createFloatingActions({
14a15,18
> 
>   $: if (open) {
>     updatePosition();
>   }

I wonder if there's a way to support this use case more automatically?

fedorovvvv commented 2 years ago

Hi! Apparently this is due to the work of Portal, possibly due to the fact that it renders content outside of the parent component

There is an updatePosition for such situations, it is perfect for non-standard cases

Thank you for reporting this, I hope it helps the others ✨