Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Renderless Flyout.Vue component
<flyout v-cloak>
<div slot-scope="props">
<button
v-on:click="props.toggle()"
v-bind:class="'border-2 p-1 ' + (props.isActive ? 'bg-green': 'bg-red')"
data-reference
>…</button>
<div
v-show="props.isActive"
class="list-reset bg-white border p-4 shadow z-10"
data-popper
>
Dropdown Content
</div>
</div>
</flyout>
<script>
import Popper from 'popper.js'
export default {
name: 'flyout',
data: function () {
return {
isActive: false,
popperOptions:
{
placement: 'bottom-start',
modifiers: {
arrow: {enabled: false},
preventOverflow: {
boundariesElement: 'viewport'
},
flip: {
behavior: ['bottom-start', 'bottom-end', 'top-start', 'top-end'],
boundariesElement: 'viewport'
}
}
}
}
},
render () {
return this.$scopedSlots.default({
isActive: this.isActive,
toggle: this.toggle
})
},
created () {},
destroyed () {
this.destroyPopper()
},
mounted () {
this.referenceElement = this.$el.querySelectorAll('[data-reference]')[0]
this.popperElement = this.$el.querySelectorAll('[data-popper]')[0]
this.popper = null
},
watch: {
isActive: function (isActive) {
(isActive) ? this.createPopper() : this.destroyPopper()
}
},
methods: {
toggle () {
this.isActive = !this.isActive
},
createPopper () {
if (this.popper) {
return
}
this.popper = new Popper(
this.referenceElement,
this.popperElement,
this.popperOptions
)
document.addEventListener('click', this.handleDocumentClick)
},
destroyPopper () {
if (!this.popper) {
return
}
this.popper.destroy()
this.popper = null
document.removeEventListener('click', this.handleDocumentClick)
},
handleDocumentClick (e) {
let target = e.target
if (
this.referenceElement === target ||
this.popperElement === target ||
this.referenceElement.contains(target) ||
this.popperElement.contains(target)
) {
return
}
this.isActive = false
}
}
}
</script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.