Vue 3 & Nuxt 3

Physics-based
toast notifications

Silky-smooth pill animations driven by spring physics.
Zero runtime dependencies.

$npm install notiv

Playground

Configure every option and fire a live toast. The code snippet updates in real time.

Autopilot expand / collapse
Action button
tssuccess
notiv.success({
  title: 'Saved!',
  description: 'Your changes have been saved.',
})

Quick Start

npm install notiv
// main.ts
import { NotivPlugin } from 'notiv'
import 'notiv/style.css'

app.use(NotivPlugin)
<!-- App.vue -->
<template>
  <NotivToaster position="top-right" theme="system" />
</template>
// anywhere in your app
import { notiv } from 'notiv'

notiv.success({ title: 'Done!', description: 'It worked.' })
notiv.error({ title: 'Oops', description: 'Something failed.' })
notiv.promise(fetchData(), {
  loading: { title: 'Loading...' },
  success: { title: 'Done!' },
  error:   { title: 'Failed' },
})

Nuxt 3

// nuxt.config.ts
export default defineNuxtConfig({
  modules: ['notiv/nuxt'],
})

NotivToaster and useNotiv() are auto-imported. Access $notiv via useNuxtApp().$notiv.

API

All methods except dismiss and clear return the toast id: string.

MethodDescription
notiv.show(opts)Generic toast — use the type option to set state
notiv.success(opts)Success state
notiv.error(opts)Error state
notiv.warning(opts)Warning state
notiv.info(opts)Info state
notiv.action(opts)Action state — pair with a button option
notiv.loading(opts)Loading spinner, duration defaults to null (persistent)
notiv.promise(p, opts)Tracks a promise: loading → success / error
notiv.dismiss(id)Remove a specific toast by id
notiv.clear(pos?)Remove all toasts, or only those at a given position

NotivOptions

Passed to every toast method. All fields are optional.

OptionTypeDefaultDescription
idstringautoStable ID — reuse to update or dismiss
titlestringPrimary text in the pill header
descriptionstringSecondary text shown when the pill expands
typeNotivStateIcon + color: success | error | warning | info | action | loading
positionNotivPositiontoaster defaultOverrides the toaster position for this toast
durationnumber | null6000Auto-dismiss ms. null = never auto-dismiss
iconComponent | VNode | nullCustom icon component. null removes it
fillstringtheme fillPill fill color — any CSS color value
roundnessnumber16Pill corner radius in px
autopilotboolean | { expand?, collapse? }trueAuto expand/collapse. false = disabled. Object = custom delays in ms
button{ title, onClick }Action button rendered in the expanded body
stylesNotivStylesCSS class overrides for sub-elements (see below)

NotivStyles — per-element class overrides

KeyApplies to
titledata-notiv-title — pill header text
descriptiondata-notiv-description — expanded body text
badgedata-notiv-badge — icon wrapper circle
buttondata-notiv-button — action button
notiv.success({
  title: 'Done',
  styles: {
    badge: 'ring-2 ring-green-400',
    title: 'font-semibold',
  },
})

NotivToaster Props

PropTypeDefaultDescription
positionNotivPosition'top-right'Default position for all toasts
theme'light' | 'dark' | 'system''system'Pill fill color scheme. system follows OS preference
offsetnumber | string | NotivOffsetConfigundefinedViewport edge inset. Number = px all sides, object = per-side
optionsNotivOptionsundefinedGlobal defaults merged into every toast
<NotivToaster
  position="top-right"
  theme="system"
  :offset="{ top: '80px', right: '1rem' }"
  :options="{ duration: 4000, roundness: 24 }"
/>

useNotiv()

Composable exposing the API and a reactive list of active toasts.

import { useNotiv } from 'notiv'

const { notiv, toasts } = useNotiv()

// optionally filter by position:
const { toasts } = useNotiv('top-right')

// toasts is a ComputedRef<NotivItem[]>
console.log(toasts.value.length)

CSS Custom Properties

Override on :root to customize layout and state colors globally.

PropertyDefaultDescription
--notiv-width350pxToast pill width
--notiv-height40pxCollapsed pill height
--notiv-duration420msSpring animation duration
--notiv-state-successoklch(0.723 0.219 142.136)Success icon & text color
--notiv-state-erroroklch(0.637 0.237 25.331)Error icon & text color
--notiv-state-warningoklch(0.795 0.184 86.047)Warning icon & text color
--notiv-state-infooklch(0.685 0.169 237.323)Info icon & text color
--notiv-state-actionoklch(0.623 0.214 259.815)Action icon & text color
--notiv-state-loadingoklch(0.556 0 0)Loading icon & text color
/* wider toasts, custom success color */
:root {
  --notiv-width: 400px;
  --notiv-state-success: oklch(0.75 0.2 160);
}

Promise API

success and error accept a callback that receives the resolved value or rejection reason.

notiv.promise(fetchUser(id), {
  loading: { title: 'Loading user...' },
  success: (user) => ({
    title: `Welcome, ${user.name}!`,
    description: 'Profile loaded.',
  }),
  error: (err) => ({
    title: 'Failed',
    description: err.message,
  }),
  position: 'bottom-right',
})
MIT License · Built for Vue 3 & Nuxt 3