vue3-notification

A lightweight, animatable toast notification component for Vue 3, triggered via an imperative API or a Composition API hook.

Library
npm
v3.4.2
401stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
43/100Fair
Development Activity4
Maintenance20
Community60
Maturity60
Momentum28

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
65/100Good
Architecture78
Code Quality65
Innovation45
Learning Curve70

@kyvg/vue3-notification is a Vue 3 port of the popular vue-notification library, giving apps a drop-in <notifications /> component plus an imperative notify()/$notify API (and a useNotification() Composition API hook) for firing toast-style alerts from anywhere in the app — components, router guards, or plain utility modules — without prop drilling or manual state wiring.

Under the hood it decouples the trigger from the display: calling notify() just emits an event on a shared mitt bus, and any mounted <notifications> instance (optionally scoped to a group) picks it up, manages its own lifecycle timers, and animates items in and out via CSS transitions or an optional Velocity.js integration. It ships as a single dependency-free bundle with inlined CSS, full TypeScript types, and an unplugin-vue-components resolver for auto-importing the component without manual registration.

What You Get

  • A global <notifications /> component you drop into your root layout, with props for position, width, max count, animation type, and custom classes.
  • Three equivalent trigger APIs: the legacy this.$notify() global property, a standalone notify() function import, and a useNotification() Composition API hook.
  • Named notification groups so you can run multiple independently-positioned notification holders (e.g. auth errors top-center, app toasts bottom-right) in the same app.
  • Full TypeScript typings plus an unplugin-vue-components auto-import resolver so the component and its types register themselves without manual app.component() calls.
  • Slot-based content override (#body) for fully custom notification markup while keeping the built-in timing/animation/lifecycle logic.

Common Use Cases

  • Form submission feedback - show a success or error toast after an async form save without adding local alert state to every component.
  • Auth flow messaging - trigger login/logout/session-expired notifications from route guards or API interceptors via the standalone notify() import, outside any component tree.
  • Multi-region alerts - run separate notification groups for system alerts vs. transactional toasts, each with its own position and styling.
  • Custom-branded toasts - replace the default markup entirely with the #body slot while keeping duration, animation, and dismiss-on-click behavior intact.

Under The Hood

Architecture From src/index.ts, the package exports the plugin’s install() (src/plugin.ts), the imperative notify/useNotification API (src/notify.ts), and the Notifications component (src/components/Notifications.tsx). install() registers a global $notify property and mounts the <notifications> component; calling notify() doesn’t touch the component directly, it emits an add event on a shared mitt-based bus (src/utils/emitter.ts). Each mounted <notifications> instance subscribes to that bus in onMounted/unsubscribes in onUnmounted, filters events by its own group prop, and maintains a local list ref of items marked IDLE or DESTROYED rather than splicing arrays directly, with per-item dismiss timers from src/utils/timer.ts (pausable via pauseOnHover) and width/position math delegated to src/utils/parser.ts and src/utils/index.ts. This event-bus decoupling is what lets multiple independently positioned notification holders coexist, but it also means the imperative API and every mounted instance share no other communication channel — a change to the emitter’s event shape would ripple through both sides at once.

Tech Stack Written in TypeScript against Vue 3 (peer dependency ^3.0.0), with the component itself authored as a TSX render function via defineComponent and @vitejs/plugin-vue-jsx. The only pub/sub abstraction, mitt, is listed as a devDependency because the package declares no runtime dependencies at all — everything is bundled into the output by Vite (vite build), with vite-plugin-dts generating type declarations and vite-plugin-css-injected-by-js inlining the component’s CSS into the JS bundle so consumers need no separate stylesheet import. A second Vite config (vite.resolver.config.js) builds the /auto-import-resolver subpath export for unplugin-vue-components integration. Docs are a VitePress site under docs/, deployed to GitHub Pages via a dedicated Actions workflow.

Code Quality Two Vitest spec files (test/unit/specs/Notifications.spec.ts, util.spec.ts) use @vue/test-utils and jsdom to cover default props, group-scoped addItem behavior, and duplicate handling, though the main spec file opens with // @ts-nocheck, disabling type-checking in the test itself. Source types are explicit (src/types.ts defines NotificationsOptions/NotificationItem), though several internal functions type notification IDs as unknown rather than a stricter union. ESLint is configured with eslint-plugin-vue, and a Node.js CI workflow runs the Vitest suite across Node 18 and 20 on every push/PR to master — but that workflow does not run npm run lint, so lint issues aren’t CI-enforced. The test suite covers the common paths but leaves position/direction math and multi-group edge cases largely untested.

API Design The library offers three parallel ways to trigger a notification — a global this.$notify() property for Options API code, a plain notify() function import for use entirely outside components (router guards, interceptors), and a useNotification() Composition API hook — all backed by the same emitter, so consumers pick whichever fits their code without behavior drift between them. Getting started requires a single app.use(Notifications) plus dropping <notifications /> into a root component, and the auto-import-resolver export removes even that manual registration step for Vite projects using unplugin-vue-components. Naming is consistent with the Vue 2 predecessor it was ported from, which lowers the migration cost for existing users but limits how much of the surface reflects fresh design thinking.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search