Modal Routes
Modal Routes can navigate modal routes with real-time URL changes for seamless browsing.
For example, imagine your website has a page called /shop
that lists various product links. When a user clicks on a product link, such as /item/5
, the details of the product are displayed in a modal, while the URL is simultaneously updated to /item/5
.
This approach offers several advantages. Not only does it help users intuitively understand their current location on the site, but it also allows them to copy and share the URL with others easily.
When a user navigates directly to /item/5
, the page is displayed normally instead of as a modal. This setup ensures that the user experience is seamless, whether accessing the item details through a link on the shop page or by entering the URL directly into the browser.
Usage
nuxt-pages-plus
module in your Nuxt project.For instance, here's how your original Nuxt project setup with two routes: /
and /info
would look like:
<template>
<div>
<NuxtLink to="/info">Go Info</NuxtLink>
</div>
</template>
In this tutorial, we will add a modal route for /info
and add a button on index.vue
. When you click the button, an info modal will pop up on the page, and the URL will change to /info
.
Preparation
First, you need to change your <NuxtPage />
in your app.vue
file.
Option 1: Replace <NuxtPage />
with <PlusModalNuxtPage />
.
<template>
- <NuxtPage />
+ <PlusModalNuxtPage />
</template>
Option 2: You can use PlusModalNuxtPage
to wrap your NuxtPage
component and pass the route
prop to it.
<template>
<PlusModalNuxtPage v-slot="{ route }">
<NuxtPage :route="route" />
</PlusModalNuxtPage>
</template>
Adding Modal Routes
First, add a new file @my-modal/info.vue
(or any name you prefer) to your ~/pages
directory:
<template>
<Teleport to="body">
<div>
<p>I am info modal</p>
<button @click="$modalRouter.close()">Close</button>
</div>
</Teleport>
</template>
<Teleport>
is a native component in Vue 3 that allows you to move components to a specified location, here moving the modal to thebody
of the document.$modalRouter.close()
is a method used to close the modal.
Displaying Modal Routes
After creating the modal route, you can now display the modal route on your page by adding a <PlusModalLink>
and <PlusModalPage>
component.
<template>
<div>
<NuxtLink to="/info">Go Info</NuxtLink>
+ <PlusModalLink to="/info">Show Info Modal</PlusModalLink>
+ <PlusModalPage name="my-modal" />
</div>
</template>
PlusModalLink
functions similarly toNuxtLink
but performs soft-navigation that changes the URL to/info
without a full page navigation.PlusModalPage
in here is used to display the content of themy-modal
modal route. When the URL is/info
, it will display the content from@my-modal/info.vue
. You can add<PlusModalPage>
to layout for showing modal in all pages or add it to a specific page like this example.
That's it! You've successfully added a modal route to your Nuxt application.
How it works?
Modal Routes uses the History
API for saving the "background view" of the modal and pass it's route to the route
prop of RouterView
. There is a Vue RFC
by @posva demonstrating the idea.
Navigation in Modal
When a modal route is opened, you can navigate to another modal route while keeping the modal open.
Consider the example of developing a gallery application:
<template>
<div>
<PlusModalLink to="/image/1">
<img src="/image/1" />
</PlusModalLink>
<PlusModalPage name="modal" />
</div>
</template>
When a user clicks on an image link (/image/1
) from the /home
page, a modal opens displaying detailed information about the image. Inside the modal, there are "Next" and "Previous" buttons allowing the user to browse through images:
<template>
<div>
Image Modal
<PlusModalLink :to="`/image/${parseInt(id) - 1}`">Prev</PlusModalLink>
<img :src="`/image/${id}`" />
<PlusModalLink :to="`/image/${parseInt(id) + 1}`">Next</PlusModalLink>
<button @click="$modalRouter.close()">Close</button>
</div>
</template>
The modal remains open as the user navigates through images, and when the "Close" button is pressed, the modal closes and the route returns to /home
.
Nested Navigation in Modal
Continuing with the gallery application example, suppose you want to open another set of modals within @modal/image/[id].vue
to view comments, such as /comments/[id]
.
<template>
<div>
Image Modal
<PlusModalLink :to="`/image/${parseInt(id) - 1}`">Prev</PlusModalLink>
<img :src="`/image/${id}`" />
<PlusModalLink :to="`/image/${parseInt(id) + 1}`">Next</PlusModalLink>
<PlusModalLink :to="`/comments/${id}`">Comments</PlusModalLink>
<button @click="$modalRouter.close()">Close</button>
</div>
</template>
<template>
<div>
Comments
<CommentsComponent :id="id" />
<button @click="$modalRouter.close()">Close</button>
</div>
</template>
The challenge arises when pressing the "Close" button in the comments modal, the default behavior would take you back to /home
. To ensure that closing the comments modal takes you back to the image modal instead of /home
, you can utilize the open
prop on PlusModalLink
.
<template>
<div>
Image Modal
<PlusModalLink :to="`/image/${parseInt(id) - 1}`">Prev</PlusModalLink>
<img :src="`/image/${id}`" />
<PlusModalLink :to="`/image/${parseInt(id) + 1}`">Next</PlusModalLink>
<PlusModalLink open :to="`/comments/${id}`">Comments</PlusModalLink>
<button @click="$modalRouter.close()">Close</button>
</div>
</template>
This adjustment ensures that upon closing the comments modal, the navigation returns to the image modal instead of defaulting back to /home
. This enhances the continuity and user experience of navigating through modals within your application.