48 lines
1.1 KiB
Vue
48 lines
1.1 KiB
Vue
<script setup>
|
|
import { onMounted, onUnmounted, ref } from 'vue';
|
|
|
|
const props = defineProps({
|
|
align: {
|
|
type: String,
|
|
default: 'right',
|
|
},
|
|
width: {
|
|
type: String,
|
|
default: '48',
|
|
},
|
|
contentClasses: {
|
|
type: String,
|
|
default: 'dropdown-menu',
|
|
},
|
|
});
|
|
|
|
const closeOnEscape = (e) => {
|
|
if (open.value && e.key === 'Escape') {
|
|
open.value = false;
|
|
}
|
|
};
|
|
|
|
onMounted(() => document.addEventListener('keydown', closeOnEscape));
|
|
onUnmounted(() => document.removeEventListener('keydown', closeOnEscape));
|
|
|
|
const open = ref(false);
|
|
</script>
|
|
|
|
<template>
|
|
<div class="position-relative">
|
|
<div @click="open = !open">
|
|
<slot name="trigger" />
|
|
</div>
|
|
|
|
<div
|
|
v-show="open"
|
|
class="dropdown-menu show position-absolute mt-2 shadow-sm"
|
|
:class="[align === 'left' ? 'start-0' : 'end-0', contentClasses]"
|
|
style="display: none; z-index: 1050;"
|
|
@click="open = false"
|
|
>
|
|
<slot name="content" />
|
|
</div>
|
|
</div>
|
|
</template>
|