Skip to navigationSkip to content

Building a simple notification solution with Nuxt 3

I needed to add a notification system to my Nuxt 3 project at work, so users would be clearly informed when a change had been saved to the database or if something went wrong. Here is the simple solution I found.

To enable any component to trigger a notification, I created a Pinia store called “notification”. The store holds state for the notification array and an action to add notifications to the store. After 2.5 seconds, the notification is removed, as we only want it to be visible for a short period.

typescript
import { defineStore } from 'pinia'
import { ref } from 'vue'

export const useNotificationsStore = defineStore('notifications', () => {

  // Store notifications in an array
  const notifications = ref<Notice[]>([])

  // Add notifications to the store and after 2.5 seconds remove the notification
  const addNotification = (
    notificationText: string,
    notificationType: 'success' | 'error' = 'success'
  ) => {
    notifications.value.push({
      text: notificationText,
      type: notificationType
    })
    setTimeout(() => {
      notifications.value.shift()
    }, 2500)
  }

  return { notifications, addNotification }
})

In my component, after saving data in the database, I can run the action with the code below. This adds a notification with the text “New description has been saved” and a type of “success”.

typescript
import { useNotificationsStore } from '~/stores/notifications'

const notificationsStore = useNotificationsStore()

const saveData = () => {
  notificationsStore.addNotification('New description has been saved')
}

To display the notifications in the UI, I created a component that imports and lists the notifications from the store in a transition-group. This way, they animate in and then fade out after 2.5 seconds. In the project that would look something like this:

typescript
<script lang="ts" setup>
import { useNotificationsStore } from '~/stores/notifications'

const notificationsStore = useNotificationsStore()
</script>

<template>
  <div>
    <transition-group name="notification-list" tag="div">
      <div v-for="(notification, index) in notificationsStore.notifications" :key="index">
        {{ notification.text }}
      </div>
    </transition-group>
  </div>
</template>

Now, when the action is used, a notification is added to the array and the UI updates. After 2.5 seconds, the notification is removed from the array and the UI updates again. This isn't an advanced system, but it is simple and suited this project perfectly.