Files
gemory/src/components/Dropdown.vue
T
2026-06-01 22:19:26 +02:00

70 lines
1.8 KiB
Vue

<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';
interface Props {
inline?: boolean;
autoClose?: boolean;
}
const props = withDefaults(defineProps<Props>(), {
inline: false,
autoClose: true
})
const isOpen = ref(false);
const doAutoClose = () => {
if (props.autoClose) {
isOpen.value = false;
}
}
useEventListener('keyup', e => {
if (e.key === 'Escape') {
doAutoClose();
}
});
</script>
<template>
<div class="dropdown" :class="{'dropdown-open': isOpen, 'dropdown-close': !isOpen}" v-on-click-outside="doAutoClose">
<button @click="isOpen = !isOpen" class="cursor-pointer">
<Transition
enter-active-class="transition-transform"
enter-from-class="rotate-180"
leave-active-class="hidden"
leave-to-class="rotate-180">
<ChevronDownIcon v-if="!isOpen" class="chevron" />
<ChevronUpIcon v-else class="chevron" />
</Transition>
<slot name="button" />
</button>
<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">
<slot />
</div>
<div v-else-if="isOpen" class="relative">
<div class="z-10 divide-y rounded-b-md absolute">
<slot />
</div>
</div>
</Transition>
</div>
</template>
<style scoped>
@reference "@/style.css";
.chevron {
@apply w-4 h-4 me-1;
}
</style>