Popup for external links

Hey so, I was planning on opening a popup when an external link is detected. I have created a component that computes when the href is an external link or not. If it isn't, it uses a NuxtLink component, all good, but when it is external, I am opening a modal/popup using reka-ui. The problem is that due to this, I can no longer right click the link to open it in a new tab as it is somewhat of a button now. How would I fix this? Do I need to go the traditional route and redirect to a different page before going out of the website? I didn't want to have to open a new page.
5 Replies
kapa.ai
kapa.ai2w ago
Hi @Mr. Afonso. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave: ---------------------- Your approach—replacing external links with a button/modal—prevents the browser’s default link behavior, including right-click actions like “Open in new tab.” This is a common trade-off when intercepting link clicks for custom modals or popups. Based on the knowledge sources, here are your options: 1. Use a Real <a> Tag for External Links
If you want users to retain browser-native behaviors (right-click, open in new tab, copy link, etc.), you should render a real <a> tag for external links. You can still show a modal on left-click by handling the click event, but you must not prevent the default action for other mouse buttons or keyboard shortcuts. This way, right-click and middle-click will work as expected. Example:
<a
:href="externalUrl"
target="_blank"
rel="noopener noreferrer"
@click="handleClick"
>
External Link
</a>

<a
:href="externalUrl"
target="_blank"
rel="noopener noreferrer"
@click="handleClick"
>
External Link
</a>

In your handleClick method, only prevent the default action for left-clicks (button 0), and allow the browser to handle other cases:
function handleClick(event) {
if (event.button === 0 && !event.metaKey && !event.ctrlKey && !event.shiftKey && !event.altKey) {
event.preventDefault();
// Open your modal here
}
// Otherwise, let the browser handle (right-click, middle-click, etc.)
}

function handleClick(event) {
if (event.button === 0 && !event.metaKey && !event.ctrlKey && !event.shiftKey && !event.altKey) {
event.preventDefault();
// Open your modal here
}
// Otherwise, let the browser handle (right-click, middle-click, etc.)
}

2. Do Not Replace the Link with a Button
If you use a button or a div, you lose all native link behaviors. The only way to preserve them is to use an actual <a> tag. 3. Redirecting to an Interstitial Page
If you want to show a warning or modal before navigating away, you could redirect to an internal interstitial page, then have that page handle the external navigation. However, this does require a page reload and is less seamless. Summary:
To preserve right-click and open-in-new-tab for external links, you must use a real <a> tag and only intercept left-clicks for your modal. This is standard web practice and is not specific to Nuxt, but aligns with how Nuxt handles external links by rendering them as <a> tags with appropriate attributes like rel="noopener noreferrer" and target="_blank" when needed NuxtLink documentation. The knowledge sources do not mention a Nuxt-specific way to intercept external links for modals while preserving all browser behaviors, so the above is the recommended approach. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai2w ago
<@310721759110496257> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
Mr. Afonso
Mr. AfonsoOP2w ago
@kapa.ai when using v-if and v-else, how can I avoid both components showing up for a split second
kapa.ai
kapa.ai2w ago
Let me check the knowledge base for you again. One moment! :books: ---------------------- When using v-if and v-else in Nuxt (or Vue), both components may briefly appear if their visibility is not handled correctly during server-side rendering (SSR) and hydration. This is often due to mismatches between the server-rendered HTML and the client-side state. To avoid this issue: - Ensure your conditional logic is deterministic and does not depend on client-only state. If the condition for v-if is only available on the client (e.g., after a fetch or in a lifecycle hook), the server and client may render different content, causing a flash. - Use SSR-aware state or composables like useFetch or useAsyncData to ensure the data is available during SSR, so the initial render matches the hydrated state. This prevents mismatches and unwanted flashes Data Fetching in Nuxt. - For client-only content, wrap it in <client-only> to ensure it only renders on the client and avoids SSR mismatches. Example:
<template>
<client-only>
<div v-if="showComponentA">Component A</div>
<div v-else>Component B</div>
</client-only>
</template>
<template>
<client-only>
<div v-if="showComponentA">Component A</div>
<div v-else>Component B</div>
</client-only>
</template>
This approach ensures that only the correct component is rendered, and avoids both showing up during hydration Handling simple hydration mismatch after fetch in Nuxt 3. If you still experience flashes, review your data-fetching and state initialization to ensure consistency between server and client. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai2w ago
<@310721759110496257> Kapa.ai is still learning and improving, please let me know how I did by reacting below.

Did you find this page helpful?