Nuxt UI 3 useOverlay() not showing modals

Header.vue
<script setup lang="ts">
import { LoginModal, RegisterModal, SubmitProductModal } from '#components';

const query = ref('');
const overlay = useOverlay();

const loginModal = overlay.create(LoginModal);
const registerModal = overlay.create(RegisterModal);
const submitProductModal = overlay.create(SubmitProductModal);

const showLoginModal = () => {
loginModal.open();
};

const showRegisterModal = () => {
registerModal.open();
};

const showSubmitProductModal = () => {
submitProductModal.open();
};
</script>

<template>
<header class="h-[60px] flex items-center justify-between gap-5">
<h1 class="text-2xl font-semibold">
<NuxtLink to="/">MySite</NuxtLink>
</h1>

<UInput
v-model="query"
icon="lucide:search"
placeholder="Search products or categories..."
class="w-full"
size="lg"
:ui="{ trailing: '-mr-1.5' }">
<template v-if="query?.length" #trailing>
<UButton
color="neutral"
variant="ghost"
size="sm"
:ui="{ leadingIcon: '!size-4' }"
class="rounded-full"
icon="lucide:x"
aria-label="Clear input"
@click="query = ''" />
</template>
</UInput>

<div class="flex items-center gap-2">
<UButton
size="lg"
color="neutral"
variant="soft"
icon="lucide:upload"
label="Submit Product"
@click="showSubmitProductModal" />
<UButton
size="lg"
color="neutral"
variant="outline"
icon="lucide:log-in"
label="Login"
@click="showLoginModal" />
<UButton
icon="lucide:user-plus"
label="Sign Up"
size="lg"
@click="showRegisterModal" />
</div>
</header>
</template>
<script setup lang="ts">
import { LoginModal, RegisterModal, SubmitProductModal } from '#components';

const query = ref('');
const overlay = useOverlay();

const loginModal = overlay.create(LoginModal);
const registerModal = overlay.create(RegisterModal);
const submitProductModal = overlay.create(SubmitProductModal);

const showLoginModal = () => {
loginModal.open();
};

const showRegisterModal = () => {
registerModal.open();
};

const showSubmitProductModal = () => {
submitProductModal.open();
};
</script>

<template>
<header class="h-[60px] flex items-center justify-between gap-5">
<h1 class="text-2xl font-semibold">
<NuxtLink to="/">MySite</NuxtLink>
</h1>

<UInput
v-model="query"
icon="lucide:search"
placeholder="Search products or categories..."
class="w-full"
size="lg"
:ui="{ trailing: '-mr-1.5' }">
<template v-if="query?.length" #trailing>
<UButton
color="neutral"
variant="ghost"
size="sm"
:ui="{ leadingIcon: '!size-4' }"
class="rounded-full"
icon="lucide:x"
aria-label="Clear input"
@click="query = ''" />
</template>
</UInput>

<div class="flex items-center gap-2">
<UButton
size="lg"
color="neutral"
variant="soft"
icon="lucide:upload"
label="Submit Product"
@click="showSubmitProductModal" />
<UButton
size="lg"
color="neutral"
variant="outline"
icon="lucide:log-in"
label="Login"
@click="showLoginModal" />
<UButton
icon="lucide:user-plus"
label="Sign Up"
size="lg"
@click="showRegisterModal" />
</div>
</header>
</template>
When I press any of the buttons, the modals are not showing. However, the modal works when I place the button inside the modal.
19 Replies
kapa.ai
kapa.ai2w ago
Hi @mdthansil. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave: ---------------------- Based on your code, I can see why your modals aren't showing when using the useOverlay composable. The issue is related to how Nuxt UI 3 handles overlays. The Missing App Component The most likely reason your modals aren't showing is that you're missing the UApp component that's required when using the useOverlay composable. In Nuxt UI 3, the App component is necessary to render overlays programmatically. You need to wrap your application with the UApp component in your app.vue file:
<template>
<UApp>
<NuxtPage />
</UApp>
</template>
<template>
<UApp>
<NuxtPage />
</UApp>
</template>
This is a significant change from Nuxt UI v2, where separate components like UModals and USlideovers were used. In v3, these have been replaced by the UApp component which uses the OverlayProvider internally. Getting-started > Changes from v2 explains this change:
The global Modals, Slideovers and Notifications components have been removed in favor the App component.
Handling Modal Results Another important aspect of the useOverlay composable is that modals need to emit a close event to properly close and return values. Make sure your modal components (LoginModal, RegisterModal, SubmitProductModal) are emitting a close event when they should close. For example, in your modal components:
<script setup>
const emit = defineEmits(['close'])

function closeModal(result) {
emit('close', result)
}
</script>

<template>
<UModal>
<!-- Modal content -->
<template #footer>
<UButton @click="closeModal(false)" label="Cancel" />
<UButton @click="closeModal(true)" label="Submit" />
</template>
</UModal>
</template>
<script setup>
const emit = defineEmits(['close'])

function closeModal(result) {
emit('close', result)
}
</script>

<template>
<UModal>
<!-- Modal content -->
<template #footer>
<UButton @click="closeModal(false)" label="Cancel" />
<UButton @click="closeModal(true)" label="Submit" />
</template>
</UModal>
</template>
As explained in the useOverlay documentation, the overlay component must emit a close event for the overlay.open() method to work properly, especially if you want to await results. Additional Considerations 1. Make sure your modal components are properly registered and imported. 2. Check that your modal components are correctly implementing the Nuxt UI Modal component structure. 3. If you're using TypeScript, ensure your component props and emits are properly typed. If you've implemented all these suggestions and still face issues, you might want to check the browser console for any errors that could provide more specific information about what's going wrong. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai2w ago
<@1109045853857005613> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
mdthansil
mdthansilOP2w ago
I have already added the UApp. This is my app.vue:
<template>
<UApp>
<NuxtLoadingIndicator />
<NuxtLayout>
<NuxtPage />
</NuxtLayout>
</UApp>
</template>
<template>
<UApp>
<NuxtLoadingIndicator />
<NuxtLayout>
<NuxtPage />
</NuxtLayout>
</UApp>
</template>
@kapa.ai
kapa.ai
kapa.ai2w ago
Let me check the knowledge base for you again. One moment! :books: ---------------------- I see that you've correctly implemented the UApp component in your app.vue file, which is the right approach for Nuxt UI 3. Since that's not the issue, let's explore other potential reasons why your modals aren't showing. Check Your Modal Components The most likely issue now is with how your modal components are implemented. For the useOverlay composable to work properly, your modal components need to be structured correctly. Each modal component (LoginModal, RegisterModal, SubmitProductModal) should: 1. Use the UModal component properly 2. Emit a close event when they should close Here's how a proper modal component should be structured:
<template>
<UModal>
<!-- Your modal content here -->

<template #footer>
<UButton @click="$emit('close')" label="Close" />
</template>
</UModal>
</template>

<script setup>
defineEmits(['close'])
</script>
<template>
<UModal>
<!-- Your modal content here -->

<template #footer>
<UButton @click="$emit('close')" label="Close" />
</template>
</UModal>
</template>

<script setup>
defineEmits(['close'])
</script>
Potential Issues with useOverlay According to the useOverlay documentation, there are some important differences from the previous useModal and useSlideover composables: - Overlays can no longer be closed using modal.close() or slideover.close() - They close automatically when a close event is fired from the opened component OR when the overlay closes itself (clicking on backdrop, pressing ESC, etc.) - To capture the return value in the parent component, you must explicitly emit a close event with the desired value Check for Errors in Console Check your browser's console for any errors that might provide more specific information about what's going wrong. This could help identify if there are any issues with component registration or other errors. Try a Simpler Test Case To isolate the issue, you could try creating a very simple modal component and test it with the useOverlay composable. This can help determine if the issue is with your specific modal components or with the overlay system itself. If you're still experiencing issues after checking these points, it might be helpful to examine the implementation of your modal components more closely to ensure they're compatible with Nuxt UI 3's overlay system. Let me know if you need more specific guidance based on your modal component implementations! ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai2w ago
<@1109045853857005613> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
mdthansil
mdthansilOP2w ago
<template>
<UModal
title="Login"
description="Login to your account to access all features.">
<template #body>
<div>Modal content</div>
</template>
</UModal>
</template>
<template>
<UModal
title="Login"
description="Login to your account to access all features.">
<template #body>
<div>Modal content</div>
</template>
</UModal>
</template>
this is my login modal @kapa.ai
kapa.ai
kapa.ai2w ago
Let me check the knowledge base for you again. One moment! :books: ---------------------- Looking at your LoginModal component, I can see why your modals aren't showing when using the useOverlay composable. There's a specific issue with how your modal component is structured. The Issue with Your Modal Component Your current LoginModal component is missing a crucial element for working with the useOverlay composable - it doesn't emit a close event. When using useOverlay, the modal component must explicitly emit a close event for the overlay system to work properly. Here's how you should modify your LoginModal component:
<script setup>
defineEmits(['close'])
</script>

<template>
<UModal
title="Login"
description="Login to your account to access all features."
@close="$emit('close')">
<template #body>
<div>Modal content</div>
</template>

<template #footer>
<div class="flex justify-end gap-2">
<UButton
label="Cancel"
color="gray"
variant="soft"
@click="$emit('close')" />
<UButton
label="Login"
@click="$emit('close', true)" />
</div>
</template>
</UModal>
</template>
<script setup>
defineEmits(['close'])
</script>

<template>
<UModal
title="Login"
description="Login to your account to access all features."
@close="$emit('close')">
<template #body>
<div>Modal content</div>
</template>

<template #footer>
<div class="flex justify-end gap-2">
<UButton
label="Cancel"
color="gray"
variant="soft"
@click="$emit('close')" />
<UButton
label="Login"
@click="$emit('close', true)" />
</div>
</template>
</UModal>
</template>
Key Changes Needed According to the useOverlay documentation, there are important requirements for modal components: 1. You must define and emit a close event 2. The modal will close automatically when this event is emitted 3. You can pass a value with the close event that will be returned when awaiting modal.open() The documentation specifically states: "In order to return a value from the overlay, the overlay.open() can be awaited. In order for this to work, however, the overlay component must emit a close event." This is a significant change from previous versions of Nuxt UI, as explained in the migration guide. Make similar changes to your RegisterModal and SubmitProductModal components, and they should start working correctly with the useOverlay composable. Let me know if you need any further clarification! ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai2w ago
<@1109045853857005613> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
mdthansil
mdthansilOP2w ago
i have added but still not wokring @kapa.ai
kapa.ai
kapa.ai2w ago
Let me check the knowledge base for you again. One moment! :books: ---------------------- I understand you've implemented the changes I suggested but your modals still aren't working with the useOverlay composable. Let's explore some additional potential issues and solutions. Additional Troubleshooting Steps 1. Check Modal Implementation: Make sure your modal component is properly implementing the v-model:open directive. In Nuxt UI 3, this is how modals control their visibility:
<template>
<UModal
v-model:open="isOpen"
title="Login"
description="Login to your account to access all features."
@close="$emit('close')">
<!-- content -->
</UModal>
</template>

<script setup>
const isOpen = ref(true) // This is important!
defineEmits(['close'])
</script>

<template>
<UModal
v-model:open="isOpen"
title="Login"
description="Login to your account to access all features."
@close="$emit('close')">
<!-- content -->
</UModal>
</template>

<script setup>
const isOpen = ref(true) // This is important!
defineEmits(['close'])
</script>

The isOpen ref should be set to true by default for the modal to be visible when opened programmatically. 2. Try Using a Slideover Instead: As a test, you could try implementing a Slideover component instead of a Modal to see if that works. The implementation is similar:
<template>
<USlideover
v-model:open="isOpen"
title="Login"
@close="$emit('close')">
<!-- content -->
</USlideover>
</template>

<script setup>
const isOpen = ref(true)
defineEmits(['close'])
</script>

<template>
<USlideover
v-model:open="isOpen"
title="Login"
@close="$emit('close')">
<!-- content -->
</USlideover>
</template>

<script setup>
const isOpen = ref(true)
defineEmits(['close'])
</script>

3. Check for Programmatic Usage Example: The Slideover documentation provides a complete example of programmatic usage that you can adapt for your needs. 4. Try a Simple Test Case: Create a very simple test case with minimal code to isolate the issue:
// TestModal.vue
<template>
<UModal v-model:open="isOpen" title="Test Modal" @close="$emit('close')">
<template #body>
<p>This is a test modal</p>
</template>
</UModal>
</template>

<script setup>
const isOpen = ref(true)
defineEmits(['close'])
</script>

// In your component where you want to open the modal
<script setup>
import { LazyTestModal } from '#components'

const overlay = useOverlay()
const modal = overlay.create(LazyTestModal)

function openModal() {
modal.open()
}
</script>

// TestModal.vue
<template>
<UModal v-model:open="isOpen" title="Test Modal" @close="$emit('close')">
<template #body>
<p>This is a test modal</p>
</template>
</UModal>
</template>

<script setup>
const isOpen = ref(true)
defineEmits(['close'])
</script>

// In your component where you want to open the modal
<script setup>
import { LazyTestModal } from '#components'

const overlay = useOverlay()
const modal = overlay.create(LazyTestModal)

function openModal() {
modal.open()
}
</script>

5. Check Console for Errors: Look for any errors in your browser's console that might provide clues about what's going wrong. If you've tried all these steps and your modals still aren't showing, please provide more details about any error messages you're seeing or additional context about your implementation. This will help me provide more targeted assistance for your specific situation. Remember that the useOverlay composable in Nuxt UI 3 works differently from previous versions, so it might take some experimentation to get it working correctly in your specific setup. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai2w ago
<@1109045853857005613> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
mdthansil
mdthansilOP2w ago
not wokrin @kapa.ai
kapa.ai
kapa.ai2w ago
Let me check the knowledge base for you again. One moment! :books: ---------------------- I understand you're still having issues with the modals not working. Since your message is very brief, I'll provide some additional troubleshooting steps that might help resolve your issue with the useOverlay composable in Nuxt UI 3. Further Troubleshooting Steps 1. Check Popover Implementation: Try using a simpler component like Popover which also works with overlays but has fewer requirements:
<template>
<UPopover>
<UButton label="Open" />
<template #content>
<div class="p-4">Test content</div>
</template>
</UPopover>
</template>

<template>
<UPopover>
<UButton label="Open" />
<template #content>
<div class="p-4">Test content</div>
</template>
</UPopover>
</template>

2. Verify Component Registration: Make sure your modal components are properly registered. Try using the Lazy prefix when creating the overlay:
const loginModal = overlay.create(LazyLoginModal);

const loginModal = overlay.create(LazyLoginModal);

3. Try Direct Implementation: Instead of using useOverlay, try implementing the modal directly in your template with v-model:open:
<template>
<UButton @click="isModalOpen = true" label="Open Modal" />
<LoginModal v-model:open="isModalOpen" />
</template>

<script setup>
const isModalOpen = ref(false)
</script>

<template>
<UButton @click="isModalOpen = true" label="Open Modal" />
<LoginModal v-model:open="isModalOpen" />
</template>

<script setup>
const isModalOpen = ref(false)
</script>

4. Check Nuxt UI Version: Ensure you're using the latest version of Nuxt UI. There might be bugs in earlier versions:
npm list @nuxt/ui

npm list @nuxt/ui

5. Nested Slideovers Example: Try implementing the nested slideovers example from the documentation to see if that works in your project. If you're still experiencing issues, please provide more detailed information about: - Any error messages in the console - Your Nuxt UI version - A more complete example of your implementation This will help me provide more targeted assistance for your specific situation. Remember that Nuxt UI 3 has significant changes from previous versions, as outlined in the migration guide. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai2w ago
<@1109045853857005613> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
mdthansil
mdthansilOP2w ago
Hey 👋 @benjamincanac, I apologize for tagging you. Am I doing this correctly?
dwol
dwol2w ago
Nuxt UI
Modal Vue Component - Nuxt UI
A dialog window that can be used to display a message or request user input.
mdthansil
mdthansilOP2w ago
I've tried that, but it's still not working.
benjamincanac
benjamincanac2w ago
Hey, I'm impressed the answers of Kapa were pretty correct. I would have asked the same 😅 If nothing worked, would you mind opening a new issue with a reproduction?
mdthansil
mdthansilOP2w ago
Hey, thank you for the response 😊 . The issue is resolved; my app.vue file was outside of the app folder, and I moved the app.vue inside the app folder. Now it's working fine.

Did you find this page helpful?