Skip to content

Instantly share code, notes, and snippets.

@lpj145
Created March 16, 2021 23:38
Show Gist options
  • Save lpj145/56aa062f39326596f26bc47cd26d4ec1 to your computer and use it in GitHub Desktop.
Save lpj145/56aa062f39326596f26bc47cd26d4ec1 to your computer and use it in GitHub Desktop.
Modal with vue3
<script lang="ts">
import './AModal.scss'
import { defineComponent, onUpdated, ref } from 'vue'
export interface AModalProps {
width?: number | string
show?: boolean
persistent?: boolean
}
export default defineComponent({
name: 'AModal',
props: {
width: {
type: [Number, String],
default: 320
},
show: {
type: Boolean,
default: false
},
persistent: Boolean
} as AModalProps,
emits: ['close'],
setup(context: { show }, attrs) {
const target = ref(null)
const notify = ref(false)
const triggerNotify = () => {
notify.value = true
setTimeout(() => {
notify.value = false
}, 200)
}
const closeModal = (event: KeyboardEvent | MouseEvent) => {
if (event instanceof KeyboardEvent && event.code === 'Escape') {
// Pressed key need be Escape and modal cannot be persistent
if (!context.persistent) {
attrs.emit('close')
return
}
//Swing modal content
triggerNotify()
}
if (event instanceof MouseEvent) {
// Close by click only possible by click on backdrop and modal cannot be persistent
if (!context.persistent && event.target === target.value) {
attrs.emit('close')
return
}
// Swing modal content
if (event.target === target.value) triggerNotify()
}
}
const toggleEscEvent = (show) => {
if (!(document instanceof Document)) return
if (show) {
document.addEventListener('keyup', closeModal)
return
}
document.removeEventListener('keyup', closeModal)
}
toggleEscEvent(context.show)
onUpdated(() => toggleEscEvent(context.show))
return {
target,
notify,
closeModal
}
}
})
</script>
<template>
<div
ref="target"
:class="{ 'a-modal--show': show }"
class="a-modal"
role="dialog"
aria-modal="true"
tabindex="-1"
@click="closeModal"
>
<div class="a-modal__content" :class="{ 'a-modal__content--notify': notify }" role="document" :style="{ maxWidth: `${width}px` }">
<slot />
</div>
</div>
</template>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment