Skip to content

Usage

Concepts

<Notivue /> is nothing than a list of empty notification containers.

For each notification created via push(), <Notivue /> creates a new container and renders its default slot content into it.

Since animations, positioning, timeouts, etc, are managed at the plugin-level and then consumed to orchestrate the containers, you have to do nothing but to design the notification itself and pass it as default slot, expecting every core feature to work out-of-the-box.

You can access the current notification item exposed via v-slot inside your component and conditionally render it as you wish. You may even pass props when creating a notification.

💡 In short, imagine as if a v-for="item in items" is silently added to the element that is passed as default slot and that items is the array holding all the notifications created via push() that are currently displayed.

Out of curiousity, try pushing some notifications using the following snippet:

vue
<script setup>
let count = 1

function pushNotification() {
  push.info({
    message: 'John Doe started following you',
    props: {
      avatarUrl: `https://i.pravatar.cc/50?u=${++count}`,
      profileScore: count,
      isProfileComplete: Math.random() > 0.5
    }
  })
}
</script>

<template>
  <Notivue v-slot="item">
    <div>
      {{ item }}
      <button @click="item.clear">Dismiss</button>
    </div>
  </Notivue>

  <button @click="pushNotification">Push</button>
</template>

You will notice that each notification contains all the necessary data to render and interact with it, including any custom prop defined when calling push.

Type definition
ts
type Obj = Record<string, any>

export interface NotivueItem<T extends Obj = Obj> {
  title: string | Ref<string>
  message: string | Ref<string>
  duration: number
  ariaLive: 'polite' | 'assertive'
  ariaRole: 'alert' | 'status'
  props: T
  id: string
  type: NotificationType
  createdAt: number
  duplicateCount: number
  clear: () => void
  destroy: () => void
  skipQueue?: boolean
  ariaLiveOnly?: boolean
  onAutoClear?: (item: NotivueItem) => void
  onManualClear?: (item: NotivueItem) => void
}

1. Create the notification

FollowerNotification.vue

vue
<script setup lang="ts">
import type { NotivueItem } from 'notivue'

export interface FollowerNotificationProps {
  avatarUrl: string
  profileUrl: string
}

defineProps<{
  item: NotivueItem<FollowerNotificationProps>
}>()
</script>

<template>
  <div class="Wrapper" :data-notification="item.type">
    <img :src="item.props.avatarUrl" />

    <div class="Content">
      <!-- 👇 Enable screen readers to announce the message
      adding role + aria-live on the text container -->
      <p :role="item.ariaRole" :aria-live="item.ariaLive" aria-atomic="true">
        {{ item.message }}
      </p>
      <a v-if="item.type === 'success'" :href="item.props.profileUrl">
        View Profile
      </a>
    </div>

    <button @click="item.clear">Dismiss</button>
  </div>
</template>

<style scoped>
.Wrapper {
  width: 400px;
  max-width: 100%;
  /* 🖕 Make it responsive */
  display: flex;
  background-color: #fff;
}

[data-notification='success'] {
  color: green;
}

[data-notification='error'] {
  color: red;
}
</style>

2. Use it as default slot

vue
<script setup lang="ts">
import type { NotivueItem } from 'notivue'

import FollowerNotification, {
  type FollowerNotificationProps
} from './FollowerNotification.vue'
</script>

<template>
  <Notivue v-slot="item">
    <FollowerNotification
      :item="item as NotivueItem<FollowerNotificationProps>"
    />
  </Notivue>

  <!-- RouterView, etc. -->
</template>

3. Push

ts
import type { FollowerNotificationProps } from './FollowerNotification.vue'

push.info<FollowerNotificationProps>({
  title: 'You have a new follower!',
  message: 'John Doe started following you, check his profile',
  props: {
    avatarUrl: 'https://i.pravatar.cc/300',
    profileUrl: 'https://github.com/smastrom'
  }
})

Which push method (or notification type) to use?

Use the method that better matches the severity of the notification so the corresponding notification options ariaLive, ariaRole and duration are retained from your configuration.