Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 | <script setup lang="ts"> import { computed, onMounted, onUnmounted, ref } from 'vue'; const props = withDefaults( defineProps<{ align?: 'left' | 'right'; width?: '48'; contentClasses?: string; }>(), { align: 'right', width: '48', contentClasses: 'py-1 bg-white dark:bg-gray-700', }, ); const closeOnEscape = (e: KeyboardEvent) => { if (open.value && e.key === 'Escape') { open.value = false; } }; onMounted(() => document.addEventListener('keydown', closeOnEscape)); onUnmounted(() => document.removeEventListener('keydown', closeOnEscape)); const widthClass = computed(() => { return { 48: 'w-48', }[props.width.toString()]; }); const alignmentClasses = computed(() => { if (props.align === 'left') { return 'ltr:origin-top-left rtl:origin-top-right start-0'; } else if (props.align === 'right') { return 'ltr:origin-top-right rtl:origin-top-left end-0'; } else { return 'origin-top'; } }); const open = ref(false); </script> <template> <div class="relative"> <div @click="open = !open"> <slot name="trigger" /> </div> <!-- Full Screen Dropdown Overlay --> <div v-show="open" class="fixed inset-0 z-40" @click="open = false" ></div> <Transition enter-active-class="transition ease-out duration-200" enter-from-class="opacity-0 scale-95" enter-to-class="opacity-100 scale-100" leave-active-class="transition ease-in duration-75" leave-from-class="opacity-100 scale-100" leave-to-class="opacity-0 scale-95" > <div v-show="open" class="absolute z-50 mt-2 rounded-md shadow-lg" :class="[widthClass, alignmentClasses]" style="display: none" @click="open = false" > <div class="rounded-md ring-1 ring-black ring-opacity-5" :class="contentClasses" > <slot name="content" /> </div> </div> </Transition> </div> </template> |