Silky-smooth pill animations driven by spring physics.
Zero runtime dependencies.
npm install notivConfigure every option and fire a live toast. The code snippet updates in real time.
notiv.success({
title: 'Saved!',
description: 'Your changes have been saved.',
})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.config.ts
export default defineNuxtConfig({
modules: ['notiv/nuxt'],
})NotivToaster and useNotiv() are auto-imported. Access $notiv via useNuxtApp().$notiv.
All methods except dismiss and clear return the toast id: string.
| Method | Description |
|---|---|
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 |
Passed to every toast method. All fields are optional.
| Option | Type | Default | Description |
|---|---|---|---|
id | string | auto | Stable ID — reuse to update or dismiss |
title | string | — | Primary text in the pill header |
description | string | — | Secondary text shown when the pill expands |
type | NotivState | — | Icon + color: success | error | warning | info | action | loading |
position | NotivPosition | toaster default | Overrides the toaster position for this toast |
duration | number | null | 6000 | Auto-dismiss ms. null = never auto-dismiss |
icon | Component | VNode | null | — | Custom icon component. null removes it |
fill | string | theme fill | Pill fill color — any CSS color value |
roundness | number | 16 | Pill corner radius in px |
autopilot | boolean | { expand?, collapse? } | true | Auto expand/collapse. false = disabled. Object = custom delays in ms |
button | { title, onClick } | — | Action button rendered in the expanded body |
styles | NotivStyles | — | CSS class overrides for sub-elements (see below) |
| Key | Applies to |
|---|---|
title | data-notiv-title — pill header text |
description | data-notiv-description — expanded body text |
badge | data-notiv-badge — icon wrapper circle |
button | data-notiv-button — action button |
notiv.success({
title: 'Done',
styles: {
badge: 'ring-2 ring-green-400',
title: 'font-semibold',
},
})| Prop | Type | Default | Description |
|---|---|---|---|
position | NotivPosition | 'top-right' | Default position for all toasts |
theme | 'light' | 'dark' | 'system' | 'system' | Pill fill color scheme. system follows OS preference |
offset | number | string | NotivOffsetConfig | undefined | Viewport edge inset. Number = px all sides, object = per-side |
options | NotivOptions | undefined | Global defaults merged into every toast |
<NotivToaster
position="top-right"
theme="system"
:offset="{ top: '80px', right: '1rem' }"
:options="{ duration: 4000, roundness: 24 }"
/>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)Override on :root to customize layout and state colors globally.
| Property | Default | Description |
|---|---|---|
--notiv-width | 350px | Toast pill width |
--notiv-height | 40px | Collapsed pill height |
--notiv-duration | 420ms | Spring animation duration |
--notiv-state-success | oklch(0.723 0.219 142.136) | Success icon & text color |
--notiv-state-error | oklch(0.637 0.237 25.331) | Error icon & text color |
--notiv-state-warning | oklch(0.795 0.184 86.047) | Warning icon & text color |
--notiv-state-info | oklch(0.685 0.169 237.323) | Info icon & text color |
--notiv-state-action | oklch(0.623 0.214 259.815) | Action icon & text color |
--notiv-state-loading | oklch(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);
}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',
})