# notify-zh — Full API Reference (LLM-friendly)
notify-zh is a zero-dependency toast/notification library for the browser (~2.7 KB gzipped). It exports one pre-initialized singleton. There are no providers, no components to mount, no CSS files to import — call a method and the toast appears.
- npm: https://www.npmjs.com/package/notify-zh
- GitHub: https://github.com/xavivzla/notify-zh
- Website: https://notify-zh.trely.agency
## Install
```bash
npm install notify-zh
# or: yarn add notify-zh / pnpm add notify-zh / bun add notify-zh
```
CDN (no bundler — exposes `window.notify`):
```html
```
## Quick start
```js
import notify from 'notify-zh'
notify.success({ message: 'Saved!' })
notify.error({ message: 'Something went wrong', time: 5000 })
notify.warning({ message: 'Check your input', title: 'Validation', position: 'bottom-right' })
notify.info({ message: 'Heads up', icon: { el: 'ℹ️' } })
// Sticky + manually dismissable
const id = notify.info({ message: 'Uploading…', time: Infinity, closable: true })
notify.dismiss(id)
// Promise tracking: loading → success/error
await notify.promise(saveUser(), {
loading: 'Saving…',
success: 'User saved!',
error: (e) => `Failed: ${e.message}`
})
notify.dismissAll() // remove every visible notification
```
## Methods
| Method | Purpose |
| --- | --- |
| `notify.success(options)` | Green toast (role="status"). Returns numeric id |
| `notify.error(options)` | Red toast (role="alert"). Returns numeric id |
| `notify.warning(options)` | Orange toast (role="alert"). Returns numeric id |
| `notify.info(options)` | Blue toast (role="status"). Returns numeric id |
| `notify.promise(promise, messages, options?)` | Sticky loading toast replaced by success/error when the promise settles. Returns the same promise |
| `notify.dismiss(id)` | Dismiss one notification by id (also removes it from the queue) |
| `notify.dismissAll()` | Dismiss all visible notifications and clear the queue |
| `notify.config(config)` | Set global defaults (call once at app startup) |
All methods are SSR-safe: outside the browser (Next.js/Nuxt server render, Node scripts) they are silent no-ops, so no `typeof window` guard is needed.
### notify.promise()
```ts
notify.promise(
promise: Promise,
messages: {
loading: string
success: string | ((value: T) => string)
error: string | ((error: unknown) => string)
},
options?: Omit // applied to all three states
): Promise
```
The original promise is returned unchanged: resolve value passes through, rejections rethrow.
## Options (per notification)
```ts
interface PropsOptions {
message: string // required — rendered as plain text (XSS-safe)
time?: number // ms before auto-close, default 3000; Infinity = sticky
position?: NotificationPosition // default 'center-top'
title?: string // optional bold title above the message (plain text)
closable?: boolean // show an accessible close (×) button, default false
icon?: { el?: string } // optional HTML string rendered before the message
// (emoji or inline SVG; only pass trusted markup)
}
type NotificationPosition =
| 'top-left' | 'top-right'
| 'bottom-left' | 'bottom-right'
| 'center-top' | 'center-bottom'
| 'center'
```
## Global config
```ts
interface PropsConfig {
defaultTime?: number // default 3000 (ms)
position?: NotificationPosition // default 'center-top'
backgrounds?: { // per-type background colors
success?: string // default '#13BF5F'
error?: string // default '#DE350B'
warning?: string // default '#F09200'
info?: string // default '#4261fb'
}
width?: string // fixed width, any CSS length e.g. '280px'
maxWidth?: string // max width, any CSS length e.g. '360px'
maxVisible?: number // cap per position; extra toasts queue (unlimited when unset)
closable?: boolean // close (×) button on every toast, default false
pauseOnHover?: boolean // pause auto-close timer on hover, default true
disableDefaultStyles?: boolean // true = library injects no CSS (required for classNames)
classNames?: {
base?: string // replaces default base class on every toast
success?: string // per-type class; when set, inline background is NOT applied
error?: string
warning?: string
info?: string
animateIn?: string // class applied while entering
animateOut?: string // class applied while leaving
}
}
```
```js
notify.config({
defaultTime: 4000,
position: 'top-right',
backgrounds: { success: '#10B981', error: '#EF4444' },
maxWidth: '360px'
})
```
## Styling with Tailwind / Bootstrap / custom CSS
Disable the built-in styles and map your own classes:
```js
notify.config({
disableDefaultStyles: true, // REQUIRED when using classNames
classNames: {
base: 'p-4 mb-2 rounded-md shadow-lg text-white max-w-sm pointer-events-auto flex items-center',
success: 'bg-green-500',
error: 'bg-red-600',
warning: 'bg-yellow-500',
info: 'bg-blue-500',
animateIn: 'animate-fade-in', // define these animations in your CSS
animateOut: 'animate-fade-out'
}
})
```
Notes:
- When a per-type class (`classNames.success`, etc.) is set, the library does not apply its inline background color for that type — your class wins.
- `animateIn`/`animateOut` replace the default fade animations; removal happens on `animationend`.
## Framework examples
### React / Next.js (client components)
```jsx
'use client' // Next.js App Router
import notify from 'notify-zh'
export default function SaveButton() {
return (
)
}
```
### Vue 3
```vue
```
### Angular
```ts
import { Component } from '@angular/core'
import notify from 'notify-zh'
@Component({
selector: 'app-demo',
template: ``
})
export class DemoComponent {
show() {
notify.info({ message: 'System maintenance upcoming.', time: 6000 })
}
}
```
### Svelte
```svelte
```
### Vanilla JS (ESM)
```html
```
## TypeScript
Types ship with the package:
```ts
import notify from 'notify-zh'
import type {
PropsOptions,
PropsConfig,
PromiseMessages,
NotificationPosition
} from 'notify-zh'
```
## Behavior details
- Notifications stack per position; each position gets its own fixed container (z-index 2000, items 9999).
- `error` and `warning` render with `role="alert"`; `success` and `info` with `role="status"` (screen-reader friendly).
- `message` and `title` are rendered via `textContent` and are XSS-safe; only `icon.el` is injected as HTML.
- Auto-close: after `time` ms the out animation plays, then the element is removed from the DOM. The timer pauses while hovered (disable with `pauseOnHover: false`).
- `time: Infinity` disables auto-close; combine with `closable: true` or `notify.dismiss(id)`.
- With `maxVisible` set, extra notifications queue per position and appear as older ones close.
- Default animations respect `prefers-reduced-motion`.
- Package formats: ESM (`dist/index.mjs`), CJS (`dist/index.js`), IIFE for CDN (`dist/index.global.js` → `window.notify`).