JAVASCRIPT
Reusable Modal Component with Vue 3 Teleport
Learn how to build a flexible and accessible modal dialog component in Vue 3 using the Teleport feature to render it outside the component's DOM hierarchy for better control.
<template>
<teleport to="body">
<div v-if="isOpen" class="modal-backdrop" @click.self="closeModal">
<div class="modal-content">
<slot></slot>
<button @click="closeModal">Close</button>
</div>
</div>
</teleport>
</template>
<script setup>
import { ref, watch } from 'vue';
const props = defineProps({
modelValue: Boolean,
});
const emit = defineEmits(['update:modelValue']);
const isOpen = ref(props.modelValue);
watch(() => props.modelValue, (newVal) => {
isOpen.value = newVal;
});
const closeModal = () => {
isOpen.value = false;
emit('update:modelValue', false);
};
</script>
<style scoped>
.modal-backdrop {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.5);
display: flex;
justify-content: center;
align-items: center;
z-index: 1000;
}
.modal-content {
background: white;
padding: 20px;
border-radius: 8px;
min-width: 300px;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
}
</style>
<!-- Usage Example: -->
<!-- <template>
<button @click="showModal = true">Open Modal</button>
<MyModal v-model="showModal">
<h2>Modal Title</h2>
<p>This is the content of my modal.</p>
</MyModal>
</template>
<script setup>
import { ref } from 'vue';
import MyModal from './MyModal.vue'; // Assuming MyModal is this component
const showModal = ref(false);
</script> -->
How it works: This snippet demonstrates how to create a reusable modal component using Vue 3's `Teleport` feature. `Teleport` allows the modal's content to be rendered into a different part of the DOM, typically 'body', regardless of where the component is used in the component tree. This prevents CSS z-index issues and ensures accessibility. The component uses `v-model` for easy two-way binding to control its visibility, and slots allow for flexible content insertion. The backdrop click closes the modal, enhancing user experience.