Skip to content

Instantly share code, notes, and snippets.

@lao9s
Created August 17, 2022 08:34
Show Gist options
  • Save lao9s/8e66aaf203bfe5a067b958c8fc9e9de0 to your computer and use it in GitHub Desktop.
Save lao9s/8e66aaf203bfe5a067b958c8fc9e9de0 to your computer and use it in GitHub Desktop.
import Dropdown from "@/Components/Dropdown.vue" <Dropdown align="left" :closeable-on-content="false" @close="$emit('close')"> <template #trigger> <button type="button" v-tooltip="'Emoji'" class="hover:text-o
<script setup>
import {computed, onMounted, onUnmounted, ref} from 'vue';
const props = defineProps({
align: {
type: String,
default: 'right',
},
widthClasses: {
type: String,
default: 'w-48',
},
contentClasses: {
type: Array,
default: () => ['py-0', 'bg-white'],
},
closeableOnContent: {
type: Boolean,
default: true,
},
});
const emit = defineEmits(['close']);
let open = ref(false);
const closeOnEscape = (e) => {
if (open.value && e.key === 'Escape') {
close();
}
};
const closeOnContentClick = () => {
if (props.closeableOnContent) {
close();
}
}
const close = () => {
open.value = false;
emit('close');
}
onMounted(() => document.addEventListener('keydown', closeOnEscape));
onUnmounted(() => document.removeEventListener('keydown', closeOnEscape));
const alignmentClasses = computed(() => {
if (props.align === 'left') {
return 'origin-top-left left-0';
}
if (props.align === 'right') {
return 'origin-top-right right-0';
}
return 'origin-top';
});
</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="close"/>
<transition
enter-active-class="transition ease-out duration-200"
enter-from-class="transform opacity-0 scale-95"
enter-to-class="transform opacity-100 scale-100"
leave-active-class="transition ease-in duration-75"
leave-from-class="transform opacity-100 scale-100"
leave-to-class="transform opacity-0 scale-95"
>
<div
v-show="open"
class="absolute z-50 mt-1 rounded-md shadow-mix"
:class="[widthClasses, alignmentClasses]"
style="display: none;"
@click="closeOnContentClick"
>
<div class="rounded-md border border-gray-200" :class="contentClasses">
<slot name="content"/>
</div>
</div>
</transition>
</div>
</template>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment