homemanager-fe/src/components/Dropdown.vue

62 lines
1.5 KiB
Vue

<template>
<div class="relative" ref="wrapper">
<slot name="trigger" :title="title" :open="open" :toggle="toggle">
<button type="button" @click="() => toggle()" :aria-expanded="open">
<span>{{ title }}</span>
<ChevronDownIcon class="ml-2 h-5 w-5" />
</button>
</slot>
<Transition
name="menu-transition"
enter-active-class="transition ease-out duration-200"
enter-from-class="opacity-0 translate-y-1"
enter-to-class="opacity-100 translate-y-0"
leave-active-class="transition ease-in duration-150"
leave-from-class="opacity-100 translate-y-0"
leave-to-class="opacity-0 translate-y-1"
>
<slot :title="title" :open="open" :toggle="toggle" v-if="open"></slot>
</Transition>
</div>
</template>
<script setup lang="ts">
import { ChevronDownIcon } from '@heroicons/vue/24/outline';
import { onBeforeUnmount, onMounted, ref } from 'vue';
import { onBeforeRouteLeave } from 'vue-router';
const open = ref(false);
const wrapper = ref();
const props = defineProps<{
title: string;
}>();
const toggle = (to?: boolean) => {
open.value = to ?? !open.value;
};
const event = (e: MouseEvent) => {
if (
wrapper.value.contains(e.target as HTMLElement) &&
!(e.target as HTMLElement).closest('a')
) {
return;
}
open.value = false;
};
onMounted(() => {
window.addEventListener('click', event);
});
onBeforeUnmount(() => {
window.removeEventListener('click', event);
});
onBeforeRouteLeave(() => {
toggle(false);
});
</script>