Appearance
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 thatitems
is the array holding all the notifications created viapush()
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.