Skip to main content
Vuetify0 is now in alpha!
Vuetify0 Logo
Theme
Mode
Palettes
Accessibility
Vuetify One
Sign in to Vuetify One

Access premium tools across the Vuetify ecosystem — Bin, Play, Studio, and more.

Not a subscriber? See what's included

useNotifications


IntermediateApr 7, 2026

Notification lifecycle management with severity levels, state mutations, toast queuing, and auto-dismiss.

Installation

Install the Notifications plugin in your app’s entry point:

main.ts
import { createApp } from 'vue'
import { createNotificationsPlugin } from '@vuetify/v0'
import App from './App.vue'

const app = createApp(App)

app.use(createNotificationsPlugin())

app.mount('#app')

Usage

Once the plugin is installed, use the useNotifications composable in any component:

vue
<script setup lang="ts">
  import { useNotifications } from '@vuetify/v0'

  const notifications = useNotifications()

  function onSave () {
    notifications.send({
      subject: 'Changes saved',
      severity: 'success',
      timeout: 3000,
    })
  }

  function onError () {
    notifications.send({
      subject: 'Build failed',
      severity: 'error',
      timeout: -1,
    })
  }
</script>

<template>
  <button @click="onSave">
    Save
  </button>
</template>

Architecture

createNotifications layers notification semantics on top of the registry and queue primitives, with plugin installation via createPluginContext:

Notification Architecture

Use controls to zoom and pan. Click outside or press Escape to close.

Notification Architecture

Severity Levels

The severity field categorizes notifications by urgency. It maps to ARIA live region roles automatically:

ValueARIA roleUse for
'error'role="alert"Failures, errors, destructive outcomes
'warning'role="alert"Degraded state, approaching limits
'info'role="status"Neutral updates, background activity
'success'role="status"Completed actions, positive outcomes

NotificationSeverity is extensible — custom values like 'critical' are accepted with autocomplete for the four defaults.

API

MethodDescription
send(input)Create notification + enqueue for toast display
register(input)Create notification in registry only (no toast). Use for historical items
queueQueue context — queue.values(), queue.pause(), queue.resume()
read(id) / unread(id)Toggle read state
seen(id)Mark as seen
archive(id) / unarchive(id)Toggle archive state
snooze(id, until) / wake(id)Snooze with expiry
readAll() / archiveAll()Bulk operations
onboard(items)Bulk-register enriched notifications into registry (no toast)
clear()Remove all notifications from the registry
dispose()Tear down event listeners and clear the registry

Examples

Notification Center

A single createNotifications instance powering four notification surfaces through the data.type field:

SurfaceTypeBehavior
Banner'banner'Persistent, dismissible, max 1 visible. System announcements, trial expiry
Toast'toast'Auto-dismissing via timeout. Action feedback: “Changes saved”
Inline'inline'Contextual, embedded in page content. Rate limits, degraded service
Inbox'inbox' or noneFull lifecycle — read, archive, snooze. Collaboration, CI alerts

The data bag drives routing — the composable doesn’t care how notifications render. Each surface filters items by data.type.

FileRole
context.tsWraps createNotifications with createContext for provide/inject
NotificationProvider.vueRenders all surfaces: banners, inbox dropdown, snackbar stack
NotificationConsumer.vueTriggers notifications — simulates real app events
inbox.vueEntry point wiring provider and consumer

Click Simulate Event repeatedly to cycle through banner, snackbar, and inbox notifications. Open the Inbox to interact with read/archive/snooze. Notice how seen (badge count) and read (visual weight) are distinct — mirroring GitHub and Slack.

Notification Lifecycle

Use controls to zoom and pan. Click outside or press Escape to close.

Notification Lifecycle
My App

Click Simulate Event to push notifications

Adapters

Adapters let you swap the underlying notification service without changing your application code.

AdapterImportDescription
createKnockAdapter@vuetify/v0/notificationsKnock↗ integration
createNovuAdapter@vuetify/v0/notificationsNovu↗ integration

Knock

Knock↗ is a notification infrastructure platform with feeds, preferences, and multi-channel delivery. Install their JavaScript SDK↗ to get started. Supports both inbound (feed → notifications) and outbound (read/archive → Knock API).

bash
pnpm add @knocklabs/client
src/main.ts
import { createApp } from 'vue'
import { createNotificationsPlugin } from '@vuetify/v0'
import { createKnockAdapter } from '@vuetify/v0/notifications'
import { feed } from './plugins/knock'
import App from './App.vue'

const app = createApp(App)

app.use(
  createNotificationsPlugin({
    adapter: createKnockAdapter(feed),
  })
)

app.mount('#app')

Novu

Novu↗ is an open-source notification infrastructure with in-app feeds, digests, and multi-channel delivery. Install their JavaScript SDK↗ to get started. Supports both inbound (feed → notifications) and outbound (read/unread/seen/archive/unarchive → Novu API).

The adapter maps Novu severity strings to NotificationSeverity by default: critical/higherror, mediumwarning, lowinfo. Pass a custom severity function to override.

bash
pnpm add @novu/js
src/main.ts
import { createApp } from 'vue'
import { createNotificationsPlugin } from '@vuetify/v0'
import { createNovuAdapter } from '@vuetify/v0/notifications'
import { novu } from './plugins/novu'
import App from './App.vue'

const app = createApp(App)

app.use(
  createNotificationsPlugin({
    adapter: createNovuAdapter(novu),
  })
)

app.mount('#app')

Custom Adapters

Implement NotificationsAdapterInterface to connect any backend:

ts
import type { NotificationsAdapterInterface, NotificationsAdapterContext } from '@vuetify/v0'

class MyBackendAdapter implements NotificationsAdapterInterface {
  setup (context: NotificationsAdapterContext) {
    // Wire inbound: push notifications into the registry
    myBackend.onMessage(msg => {
      context.send({ id: msg.id, title: msg.title, body: msg.body })
    })

    // Wire outbound: sync read/archive actions back to the backend
    context.on('notification:read', (data: any) => {
      myBackend.markRead(data.id)
    })
  }

  dispose () {
    myBackend.disconnect()
  }
}

app.use(createNotificationsPlugin({ adapter: new MyBackendAdapter() }))

Adapter context methods:

MethodPurpose
send(input)Register and enqueue for toast display (real-time inbound)
register(input)Register in history only — no toast (initial/historical load)
on(event, handler)Subscribe to outbound lifecycle events
off(event, handler)Unsubscribe from a lifecycle event

Custom Ticket Fields

Extend NotificationInput to add domain-specific fields. Pass the type parameter through the adapter and plugin:

ts
import type { NotificationInput, NotificationsAdapterInterface, NotificationsAdapterContext } from '@vuetify/v0'

interface AppNotification extends NotificationInput {
  priority: 'low' | 'medium' | 'high'
  imageUrl?: string
}

class MyBackendAdapter implements NotificationsAdapterInterface<AppNotification> {
  setup (context: NotificationsAdapterContext<AppNotification>) {
    myBackend.onMessage(msg => {
      context.send({
        id: msg.id,
        subject: msg.title,
        priority: msg.priority,    // custom field
        imageUrl: msg.imageUrl,    // custom field
      })
    })
  }
}

app.use(createNotificationsPlugin<AppNotification>({ adapter: new MyBackendAdapter() }))

Custom fields are preserved on the ticket and accessible anywhere you inject the notifications context.

Ask AI
How do I write a custom adapter for my backend?

API Reference

The following API details are for the useNotifications composable.

Functions

createNotifications

(options?: NotificationsOptions) => NotificationsContext<NotificationInput, NotificationTicket<NotificationInput>>

createNotificationsContext

<_E>(_options?: NotificationsPluginOptions | undefined) => ContextTrinity<_E>

createNotificationsPlugin

(_options?: NotificationsPluginOptions | undefined) => Plugin

useNotifications

<_E>(namespace?: string) => _E

Options

events

boolean | undefined

Enable event emission for registry operations

Default: false

reactive

boolean | undefined

Enable reactive behavior for registry operations

Default: false

timeout

number | undefined

Default auto-dismiss timeout in ms for the toast queue.

Default: 3000

Properties

collection

ReadonlyMap<ID, E>

The collection of tickets in the registry

size

number

The number of tickets in the registry

queue

QueueContext<QueueTicketInput<unknown>, QueueTicket<QueueTicketInput<unknown>>>

The toast display queue. Access `queue.values()`, `queue.pause()`, `queue.resume()`.

Methods

clear

() => void

Clear the entire registry

has

(id: ID) => boolean

Check if a ticket exists by ID

keys

() => readonly ID[]

Get all registered IDs

browse

(value: E["value"]) => ID[] | undefined

Browse for an ID(s) by value

lookup

(index: number) => ID | undefined

lookup a ticket by index number

get

(id: ID) => E | undefined

Get a ticket by ID

upsert

(id: ID, ticket?: Partial<Z>, event?: string) => E

Update or insert a ticket by ID

values

() => readonly E[]

Get all values of registered tickets

entries

() => readonly [ID, E][]

Get all entries of registered tickets

register

(ticket?: Partial<Z & RegistryTicket>) => E

Register a new ticket

unregister

(id: ID) => void

Unregister a ticket by ID

reindex

() => void

Reset the index directory and update all tickets

move

(id: ID, toIndex: number) => E | undefined

Seek for a ticket based on direction and optional predicate

seek

(direction?: "first" | "last", from?: number, predicate?: (ticket) => boolean) => E | undefined

on

<K extends Extensible<RegistryEventName>>(event: K, cb: EventHandler<E, K>) => void

Listen for registry events

off

<K extends Extensible<RegistryEventName>>(event: K, cb: EventHandler<E, K>) => void

Stop listening for registry events

emit

<K extends Extensible<RegistryEventName>>(event: K, data: EventPayload<E, K>) => void

Emit an event with data

dispose

() => void

Clears the registry and removes all listeners

onboard

(registrations: Partial<Z & RegistryTicket>[]) => E[]

Onboard multiple tickets at once

offboard

(ids: ID[]) => void

Offboard multiple tickets at once

batch

<R>(fn: () => R) => R

Execute operations in a batch, deferring cache invalidation and event emission until complete

send

(input: Z) => E

Create a notification and enqueue for toast display.

read

(id: ID) => void

Mark as read. Emits `notification:read`.

unread

(id: ID) => void

Mark as unread. Emits `notification:unread`.

seen

(id: ID) => void

Mark as seen. Emits `notification:seen`.

archive

(id: ID) => void

Archive. Emits `notification:archived`.

unarchive

(id: ID) => void

Restore from archive. Emits `notification:unarchived`.

snooze

(id: ID, until: Date) => void

Snooze until the given time. Emits `notification:snoozed`.

wake

(id: ID) => void

Cancel snooze. Emits `notification:unsnoozed`.

readAll

() => void

Mark all unread notifications as read.

archiveAll

() => void

Archive all unarchived notifications.

Was this page helpful?

© 2016-1970 Vuetify, LLC
Ctrl+/