smelte icon indicating copy to clipboard operation
smelte copied to clipboard

Popup and viewport anchoring

Open j3rem1e opened this issue 5 years ago • 3 comments

The various popup shown can be placed outside the viewport, making them hard to view/use.

For example, a tooltip can be partially hidden if the activator is in the right of the screen, or a menu can be longer than the viewport height.

Smelte should probably provides utils to position popup on the viewport.

(by the way, thanks for your work, smelte is great :)

j3rem1e avatar Jan 08 '20 08:01 j3rem1e

@matyunya A more straightforward way would be to use popper.js to manage the positioning of such popups. I can try and open PR for that if that's ok.

ajitsinghkamal avatar Jan 13 '21 14:01 ajitsinghkamal

Would love to see this! Yes please open a PR

i8ramin avatar Jan 29 '21 20:01 i8ramin

FYI, here is my code for a custom Menu implementation using popper.js + svelte-popperjs. Its a mashup of code borrowed from the Menu implementation from Smelte and code from the demo for svelte-popperjs. Just sharing just in case it helps.

<script lang="ts">
  import type { Placement } from '@popperjs/core/lib'
  import { createPopperActions } from 'svelte-popperjs'

  import { fly } from 'svelte/transition'
  import { quadOut, quadIn } from 'svelte/easing'

  export let open = false

  const inProps = { y: 10, duration: 200, easing: quadIn }
  const outProps = { y: -10, duration: 100, easing: quadOut, delay: 100 }

  const [popperRef, popperContent] = createPopperActions()
  const popperOptions = {
    placement: 'bottom-start' as Placement,
    modifiers: [{ name: 'offset', options: { offset: [0, 8] } }],
  }
</script>

<svelte:window on:click={() => (open = false)} />

<div
  use:popperRef
  on:click={(event) => {
    // stop event propagation so we don't trigger
    // the svelte:window on:click above
    event.stopPropagation()
    open = !open
  }}
>
  <slot name="trigger" />
</div>

{#if open}
  <div id="tooltip" class="absolute z-10" use:popperContent={popperOptions}>
    <div class="w-auto bg-white rounded elevation-3" in:fly={inProps} out:fly={outProps}>
      <slot />
    </div>
  </div>
{/if}

i8ramin avatar Jan 30 '21 18:01 i8ramin