• Fri, Mar 2026

Real-World Example: Teleporting Notifications

Real-World Example: Teleporting Notifications

We already explored how Vue 3 can be used to build reusable modals that “escape” the DOM hierarchy. But Teleport isn’t just for modals. Another powerful use case is notifications (toasts). Notifications are meant to appear globally, usually at the top-right or bottom of the screen, no matter where in the app they were triggered. Teleport is perfect for this.

Real-World Example: Teleporting Notifications

Imagine we want to build a reusable notification system where components from anywhere in the app can trigger a global toast. Instead of deeply nesting this in the DOM, we’ll teleport it to a dedicated #notifications container.

Step 1: Add a Notification Target in index.html


<body>
  <div id="app"></div>
  <div id="modals"></div>
  <div id="notifications"></div>
</body>

Step 2: Create Notification Component

This component will display a list of notifications. It will be teleported into #notifications.



<template>
  <teleport to="#notifications">
    <div class1="notification-wrapper">
      <div 
        v-for="note in notifications" 
        :key="note.id" 
        class1="notification">
        {{ note.message }}
      </div>
    </div>
  </teleport>
</template>

<script setup>
import { inject } from 'vue'

const notifications = inject('notifications')
</script>

Step 3: Provide Notifications State

We’ll use Vue’s provide/inject to share a global notification state.



<template>
  <div>
    <h1>Vue 3 Teleport Notifications Example</h1>
    <button @click="addNotification">Show Notification</button>

    <NotificationList />
  </div>
</template>

<script setup>
import { ref, provide } from 'vue'
import NotificationList from './NotificationList.vue'

const notifications = ref([])
provide('notifications', notifications)

let counter = 0
function addNotification() {
  counter++
  notifications.value.push({
    id: counter,
    message: `Notification #${counter}`
  })
  // Auto-remove after 3 seconds
  setTimeout(() => {
    notifications.value = notifications.value.filter(n => n.id !== counter)
  }, 3000)
}
</script>

Here, the NotificationList component is teleported into the global #notifications div, but it still reacts to the state provided in App.vue. When you click “Show Notification,” a new toast appears in the global container and disappears after 3 seconds.

Step 4: Adding Multiple Notifications

Because we’re using an array of notifications, the system already supports multiple toasts. Each one is displayed independently and auto-dismisses after a timeout.

Benefits of Teleport for Notifications

  • No CSS conflicts: Notifications appear above all app content without worrying about container styles.
  • Reusable: You can drop <NotificationList> into any app, and it will render correctly.
  • Reactive: Notifications update dynamically because they’re tied to reactive state.

Full Example: Modal + Notifications Together

Let’s combine what we’ve learned by building an app with both a modal system and a notification system, both powered by Teleport.



<template>
  <div>
    <h1>Vue 3 Teleport: Modal + Notifications</h1>
    <button @click="showModal = true">Open Modal</button>
    <button @click="addNotification">Show Notification</button>

    <Modal :visible="showModal" @close="showModal = false">
      <h2>This is a Modal</h2>
      <p>It uses Teleport to render outside the DOM hierarchy.</p>
    </Modal>

    <NotificationList />
  </div>
</template>

<script setup>
import { ref, provide } from 'vue'
import Modal from './Modal.vue'
import NotificationList from './NotificationList.vue'

const showModal = ref(false)
const notifications = ref([])
provide('notifications', notifications)

let counter = 0
function addNotification() {
  counter++
  notifications.value.push({
    id: counter,
    message: `Notification #${counter}`
  })
  setTimeout(() => {
    notifications.value = notifications.value.filter(n => n.id !== counter)
  }, 3000)
}
</script>

Now you’ve got a polished UI system where modals and notifications both teleport to their respective global containers, solving layout headaches while keeping your code clean.

Final Thoughts

With Vue 3 Teleport, building advanced UI patterns like modals and notifications becomes a breeze. Instead of fighting with DOM hierarchies and CSS quirks, you focus on reactivity and UX. By combining Teleport with provide/inject, you can manage global state elegantly and render UI elements exactly where they belong in the DOM. This is Vue’s philosophy at its best: simplicity, reactivity, and flexibility.

This website uses cookies to enhance your browsing experience. By continuing to use this site, you consent to the use of cookies. Please review our Privacy Policy for more information on how we handle your data. Cookie Policy