Update!
Found out that I can't use Inertia's <Link> component when triggering the modal. Somehow it made an XHR call which resets the ref state.
Changed it to a and not it works :)
Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.
I am trying to create a reusable modal component with headless ui's modal component. So far I've created the component and placed it in the page that needs the modal.
I have defined the expose in the child component as so:
<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">
<DialogTitle as="h3" class="text-lg font-medium leading-6 text-gray-900"> Payment successful </DialogTitle>
<div class="mt-2">
<p class="text-sm text-gray-500">Your payment has been successfully submitted. We’ve sent you an email with all of the details of your order.</p>
</div>
<div class="mt-4">
<button
type="button"
class="inline-flex justify-center px-4 py-2 text-sm font-medium text-blue-900 bg-blue-100 border border-transparent rounded-md hover:bg-blue-200 focus:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-blue-500"
@click="closeModal"
>
Got it, thanks!
</button>
</div>
</div>
</TransitionChild>
</div>
</div>
</Dialog>
</TransitionRoot>
</template>
<script setup>
import { ref } from 'vue';
import { TransitionRoot, TransitionChild, Dialog, DialogOverlay, DialogTitle } from '@headlessui/vue';
const isOpen = ref(false);
function closeModal() {
isOpen.value = false;
}
function openModal() {
isOpen.value = true;
}
defineExpose({
openModal,
closeModal
})
</script>
<template>
<AuthBase>
<template #title>Brugere</template>
... more irrelevant code ...
<ThePagination :links="users.meta.links" :meta="users.meta" />
<TheModal ref="modal"></TheModal>
</AuthBase>
</template>
<script setup>
import { Menu, MenuButton, MenuItem, MenuItems } from '@headlessui/vue';
import { ChevronDownIcon } from '@heroicons/vue/solid';
import { Inertia } from '@inertiajs/inertia';
import { ref, watch } from '@vue/runtime-core';
import debounce from 'lodash/debounce';
let props = defineProps({
users: Object,
filters: Object,
});
let search = ref(props.filters.search);
watch(
search,
debounce(function (value) {
Inertia.get(
'/brugere',
{ search: value },
{
preserveState: true,
replace: true,
}
);
}, 300)
);
let modal = ref();
function openModal() {
modal.value.openModal();
}
</script>
When I am trying to fire the openModal() function, then it opens the modal but closes again, almost immediately. I've been trying different things for the past 3-4 hours, and I can't seem to find whats wrong?
Thank you in advance!
Found out that I can't use Inertia's <Link> component when triggering the modal. Somehow it made an XHR call which resets the ref state.
Changed it to a and not it works :)
Please or to participate in this conversation.