ycs77 / headlessui-float

Easily use Headless UI with Floating UI to position floating elements.
https://headlessui-float.vercel.app
MIT License
344 stars 11 forks source link

TypeError: 'string' is not assignable to type 'Placement | undefined'.ts(2322) #37

Closed whitespacecode closed 1 year ago

whitespacecode commented 1 year ago

Use Version Use version when bugs appear:

Describe the bug I'm converting the provided example code to be used as a component with properties. Using props to define placement gives a type error.

To Reproduce

<script` setup lang="ts">
import { Popover, PopoverButton, PopoverPanel } from '@headlessui/vue'
import { Float, FloatArrow } from '@headlessui-float/vue'
import { defineProps } from "vue"

export interface Props {
    placement?: string
    labels?: string[]
    useArrow?: boolean 
}

const props = withDefaults(defineProps<Props>(), {
    placement: 'bottom-start',
    labels: () => ['one', 'two'],
    useArrow: false,
})
</script>

<template>
      <Popover>
        <Float :placement="placement"
                :offset="15"
                :shift="6"
                :flip="10"
                :arrow="useArrow"
                portal
                enter="transition duration-200 ease-out"
                enter-from="opacity-0 -translate-y-1"
                enter-to="opacity-100 translate-y-0"
                leave="transition duration-150 ease-in"
                leave-from="opacity-100 translate-y-0"
                leave-to="opacity-0 -translate-y-1"
        >
            <PopoverButton class="px-5 py-2 bg-indigo-50 hover:bg-indigo-100 text-indigo-500 flex justify-center items-center rounded">
                Click me
            </PopoverButton>

            <PopoverPanel class="w-[240px] h-[70px] bg-white border border-gray-200 rounded-md shadow-lg focus:outline-none">
                <FloatArrow v-if="useArrow" class="absolute bg-white w-5 h-5 rotate-45 border border-gray-200" />
                <div class="relative h-full bg-white p-3  rounded-md">
                    Popover & arrow, content...
                </div>
            </PopoverPanel>
        </Float>
      </Popover>
</template>

Screenshots

image

Expected behavior Define the property placement as String in the package so the type error would be gone.

ycs77 commented 1 year ago

Hi @JoeriTheGreat, you must replace string with Placement to pass the type check, the Placement type defined the 12 placement string (see: https://floating-ui.com/docs/computePosition#placement), it's better than string for this.

  1. install @floating-ui/dom for your project, run npm i @floating-ui/dom or yarn add @floating-ui/dom
  2. change to following code:
<script setup lang="ts">
import { Popover, PopoverButton, PopoverPanel } from '@headlessui/vue'
import { Float, FloatArrow } from '@headlessui-float/vue'
import { defineProps } from "vue"
+import type { Placement } from '@floating-ui/dom'

export interface Props {
-   placement?: string
+   placement?: Placement
    labels?: string[]
    useArrow?: boolean 
}

const props = withDefaults(defineProps<Props>(), {
    placement: 'bottom-start',
    labels: () => ['one', 'two'],
    useArrow: false,
})
</script>

<template>
    ...
</template>