forked from vikunja/frontend
67 lines
1.2 KiB
Vue
67 lines
1.2 KiB
Vue
<template>
|
|
<slot name="trigger" :isOpen="open" :toggle="toggle"></slot>
|
|
<div class="popup" :class="{'is-open': open}" ref="popup">
|
|
<slot name="content"/>
|
|
</div>
|
|
</template>
|
|
|
|
<script>
|
|
import {closeWhenClickedOutside} from '@/helpers/closeWhenClickedOutside'
|
|
import {onBeforeUnmount, onMounted, ref} from 'vue'
|
|
|
|
export default {
|
|
setup() {
|
|
const open = ref(false)
|
|
const popup = ref(null)
|
|
|
|
const toggle = () => {
|
|
open.value = !open.value
|
|
}
|
|
|
|
const hidePopup = e => {
|
|
if (!open.value) {
|
|
return
|
|
}
|
|
|
|
// we actually want to use popup.$el, not its value.
|
|
// eslint-disable-next-line vue/no-ref-as-operand
|
|
closeWhenClickedOutside(e, popup.value, () => {
|
|
open.value = false
|
|
})
|
|
}
|
|
|
|
onMounted(() => {
|
|
document.addEventListener('click', hidePopup)
|
|
})
|
|
|
|
onBeforeUnmount(() => {
|
|
document.removeEventListener('click', hidePopup)
|
|
})
|
|
|
|
return {
|
|
open,
|
|
toggle,
|
|
popup,
|
|
}
|
|
},
|
|
}
|
|
</script>
|
|
|
|
<style scoped lang="scss">
|
|
.popup {
|
|
transition: opacity $transition;
|
|
opacity: 0;
|
|
height: 0;
|
|
overflow: hidden;
|
|
position: absolute;
|
|
top: 1rem;
|
|
margin: 0 !important;
|
|
|
|
&.is-open {
|
|
opacity: 1;
|
|
height: auto;
|
|
margin: 1rem 0 !important;
|
|
}
|
|
}
|
|
</style>
|