I want to use headless ui modal in vue3 but the problem is I don't understand how I can toggle the modal from parent (App.vue) if the modal is a component.
I tried to pass a prop in the Modal.vue but it's not working, my strategy was to use a modalActive prop and watch it and call appropriate function to toggle the modal, but it's simply not working.
The example in headless UI uses a button but that's inside the component it self so obviously it can access functions of that component without problem.
My code:
App.vue
<template>
<Modal>
<template v-slot:default>
<LoginForm />
</template>
</Modal>
</template>
<script setup lang="ts">
import Modal from './components/Modal.vue';
import LoginForm from './components/LoginForm.vue';
import { ref } from 'vue';
</script>
Modal.vue
<template>
<TransitionRoot appear :show="isOpen" as="template">
<Dialog as="div" @close="closeModal">
<div class="fixed inset-0 z-10 overflow-y-auto">
<div class="min-h-screen px-4 text-center">
<TransitionChild
as="template"
enter="duration-300 ease-out"
enter-from="opacity-0"
enter-to="opacity-100"
leave="duration-200 ease-in"
leave-from="opacity-100"
leave-to="opacity-0"
>
<DialogOverlay class="fixed inset-0" />
</TransitionChild>
<span class="inline-block h-screen align-middle" aria-hidden="true">​</span>
<TransitionChild
as="template"
enter="duration-300 ease-out"
enter-from="opacity-0 scale-95"
enter-to="opacity-100 scale-100"
leave="duration-200 ease-in"
leave-from="opacity-100 scale-100"
leave-to="opacity-0 scale-95"
>
<div
class="inline-block w-full max-w-md p-6 my-8 overflow-hidden text-left align-middle transition-all transform bg-white shadow-xl rounded-2xl"
>
<slot></slot> <!-- slot for forms -->
</div>
</TransitionChild>
</div>
</div>
</Dialog>
</TransitionRoot>
</template>
<script setup lang="ts">
import { ref, watch } from 'vue'
import {
TransitionRoot,
TransitionChild,
Dialog,
DialogOverlay,
DialogTitle,
} from '@headlessui/vue'
const isOpen = ref(true)
function closeModal() {
isOpen.value = false
}
function openModal() {
isOpen.value = true
}
</script>