dropdown floating

This commit is contained in:
Sirttas
2026-06-01 22:29:06 +02:00
parent 05210fea4b
commit 5c12a8af43
3 changed files with 36 additions and 23 deletions
+35 -8
View File
@@ -1,8 +1,8 @@
<script setup lang="ts">
import {ChevronDownIcon, ChevronUpIcon} from '@heroicons/vue/24/outline';
import {vOnClickOutside} from '@vueuse/components';
import {useEventListener} from '@vueuse/core';
import {ref} from 'vue';
import {useElementBounding, useEventListener} from '@vueuse/core';
import {computed, ref} from 'vue';
interface Props {
inline?: boolean;
@@ -15,6 +15,16 @@ const props = withDefaults(defineProps<Props>(), {
})
const isOpen = ref(false);
const root = ref<HTMLElement | null>(null);
const floating = ref<HTMLElement | null>(null);
const { left, bottom, width } = useElementBounding(root);
const floatingStyle = computed(() => ({
left: `${left.value}px`,
top: `${bottom.value}px`,
minWidth: `${width.value}px`,
}));
const doAutoClose = () => {
if (props.autoClose) {
@@ -30,7 +40,7 @@ useEventListener('keyup', e => {
</script>
<template>
<div class="dropdown" :class="{'dropdown-open': isOpen, 'dropdown-close': !isOpen}" v-on-click-outside="doAutoClose">
<div ref="root" class="dropdown" :class="{'dropdown-open': isOpen, 'dropdown-close': !isOpen}" v-on-click-outside="[doAutoClose, { ignore: [floating] }]">
<button @click="isOpen = !isOpen" class="cursor-pointer">
<Transition
enter-active-class="transition-transform"
@@ -51,12 +61,21 @@ useEventListener('keyup', e => {
<div v-if="inline && isOpen">
<slot />
</div>
<div v-else-if="isOpen" class="relative">
<div class="z-10 divide-y rounded-b-md absolute">
<slot />
</div>
</div>
</Transition>
<Teleport to="body">
<Transition
enter-active-class="transition-opacity"
enter-from-class="opacity-0"
leave-from-class="transition-opacity"
leave-to-class="opacity-0">
<div v-if="!inline && isOpen" ref="floating" class="dropdown-floating" :style="floatingStyle">
<div class="divide-y rounded-b-md">
<slot />
</div>
</div>
</Transition>
</Teleport>
</div>
</template>
@@ -66,4 +85,12 @@ useEventListener('keyup', e => {
.chevron {
@apply w-4 h-4 me-1;
}
.dropdown-floating {
@apply fixed z-10;
}
.dropdown-floating > div {
@apply bg-slate-800 rounded-b-md shadow-lg;
}
</style>