React toast · Vue · Svelte · vanilla · zero deps

alert-notify

Tiny toast notifications for React and everything else.~4.7KB gzipped JS — a lightweight alternative to react-toastify, react-hot-toast, Sonner, and react-alert. No root provider required.

Try itHow to use
npm i alert-notify

Live demo

Fire toasts from the browser. Same API every framework gets.

Mode

Complete API reference

Nothing is required beyond importing the package and CSS. The portal auto-mounts. Below is every method, option, and default.

Required setup

import { toast } from "alert-notify";
import "alert-notify/style.css";

// That's it. No provider. No root container.
toast.success("Hello");

Methods

MethodReturnsDescription
toast(title, options?)ToastIdGeneric toast (message type)
toast.success(title, options?)ToastIdSuccess toast
toast.error(title, options?)ToastIdError toast
toast.warning(title, options?)ToastIdWarning toast
toast.info(title, options?)ToastIdInfo toast
toast.loading(title, options?)ToastIdLoading toast (sticky by default)
toast.message(title, options?)ToastIdNeutral message toast
toast.promise(promise, messages)Promise<T>Loading → success/error on same id
toast.dismiss(id?)voidDismiss one toast, or all if omitted
toast.config(partial)voidUpdate global toaster defaults
toast.getConfig()ToasterConfigRead current global config
toast.getToasts()ToastRecord[]Current toast list (headless)
toast.subscribe(listener)() => voidSubscribe to toast list changes
toast.destroy()voidDismiss all + remove portal
createToaster(config?, options?)ToasterInstanceIsolated toaster (multi-instance)

Per-toast options

Passed as the second argument to any toast.* method.

OptionTypeDefaultDescription
idstringauto UUIDStable id. Same id updates in place (coalesce)
typeToastTypefrom methodsuccess | error | warning | info | loading | message
descriptionstringSecondary text under the title
durationnumberconfig / Infinity for loadingMs until auto-close. Use Infinity for sticky
iconstring | HTMLElement | falsebuilt-in SVGCustom icon HTML/node, or false to hide
htmlstringOpt-in unescaped title HTML (prefer plain text)
action{ label, onClick }Primary action button (e.g. Undo)
cancel{ label, onClick }Secondary cancel button
closeButtonbooleanfrom config (true)Show × button
dismissiblebooleanfrom config (true)Allow swipe / close dismiss
importantbooleanfalseJump to front of the queue
classNamestringExtra class on the toast element
styleobjectInline styles on the toast
onDismiss(toast) => voidManual dismiss (close / swipe / dismiss)
onAutoClose(toast) => voidFired when duration timer ends

Global config (toast.config)

Sets defaults for all toasts. Optional wrappers pass the same props.

KeyTypeDefaultDescription
positionToastPosition"top-right"6 corners + top/bottom center
theme"light" | "dark" | "system""system"Color scheme. System also tracks html.dark / data-theme
durationnumber4000Default auto-close ms
closeButtonbooleantrueShow close button by default
dismissiblebooleantrueAllow dismiss by default
richColorsbooleanfalseTinted success/error/warning/info surfaces
visibleToastsnumber3Max visible in the stack
expandbooleanfalseAlways expand stack (else expand on hover)
gapnumber12Gap between expanded toasts (px)
offsetnumber | string16Distance from viewport edge
dir"ltr" | "rtl" | "auto""auto"Text direction
pauseOnHoverbooleantruePause timers while hovering the stack
pauseOnWindowBlurbooleantruePause timers when the window loses focus
progressBarbooleantrueShow duration progress bar
toasterClassNamestringClass on the toaster container
styleobjectInline styles on the toaster container

Promise API

toast.promise(uploadFile(), {
  loading: "Uploading…",
  success: (file) => `Uploaded ${file.name}`,
  error: (err) => (err instanceof Error ? err.message : "Failed"),
});

// Or pass full option objects:
toast.promise(save(), {
  loading: { title: "Saving…", description: "Please wait" },
  success: { title: "Saved", duration: 3000 },
  error: { title: "Failed", important: true },
});

Multiple toasters & headless

import { createToaster } from "alert-notify";

// Isolated instance (own portal + config)
const modalToast = createToaster({ position: "bottom-center" });
modalToast.success("Saved in modal");

// Headless — you render the UI
const headless = createToaster({}, { headless: true });
headless.subscribe((toasts) => {
  // render custom UI from toasts[]
});

Optional framework wrappers

Not required. They only sync config from props. Accept the same keys as toast.config.

ImportUsage
alert-notify/react<Toaster position="top-right" richColors />
alert-notify/vue<Toaster position="top-right" :rich-colors="true" />
alert-notify/svelte<Toaster position="top-right" richColors />

Behavior notes

Built for the smallest useful toast

Looking for a React toast, snackbar, or notification library that does not crush your bundle? Core JS is about 4.7KB gzip(16,006 bytes minified). CSS is optional and ~2.3KB gzip. No runtime dependencies. Tree-shake friendly ESM + CJS + CDN builds.

4.7KBJS gzip
2.3KBCSS gzip
0deps

Compared with common React toast / toastify libraries (approx. gzip JS):

  • alert-notify ~4.7KB — React, Vue, Svelte, Angular, vanilla
  • react-hot-toast ~4–5KB — React only
  • Sonner ~10–12KB — React only
  • react-toastify (toastify) ~40KB+ — React only

React toast, notifications, alerts & snackbars

One API for the jobs people usually split across react toast, react notification, react-alert, and snackbar packages. Works the same in Vue, Svelte, Angular, Astro, and CDN HTML.

How to use

Import styles once. Call toast.* from anywhere. Optional <Toaster /> wrappers only sync config props — the portal auto-mounts.

import { toast } from "alert-notify";
import "alert-notify/style.css";

toast.success("Saved");
toast.error("Failed", { description: "Try again" });
// No container. Portal mounts itself.
// App.tsx
import { toast } from "alert-notify";
import { Toaster } from "alert-notify/react";
import "alert-notify/style.css";

export function App() {
  return (
    <>
      <Toaster position="top-right" richColors />
      <button onClick={() => toast.success("Saved")}>Save</button>
    </>
  );
}
<!-- App.vue -->
<script setup>
import { toast } from "alert-notify";
import { Toaster } from "alert-notify/vue";
import "alert-notify/style.css";
</script>

<template>
  <Toaster position="top-right" rich-colors />
  <button @click="toast.success('Saved')">Save</button>
</template>
<!-- +layout.svelte / App.svelte -->
<script>
  import { toast } from "alert-notify";
  import Toaster from "alert-notify/svelte";
  import "alert-notify/style.css";
</script>

<Toaster position="top-right" richColors />
<button on:click={() => toast.success("Saved")}>Save</button>
// any.component.ts
import { toast } from "alert-notify";
import "alert-notify/style.css";

show() {
  toast.success("Saved");
}

// Optional: call toast.config({...}) once in AppComponent.ngOnInit
// No Angular module or container component required.
---
// client script or framework island
---
<script>
  import { toast } from "alert-notify";
  import "alert-notify/style.css";
  document.querySelector("button")?.addEventListener("click", () => {
    toast.success("Saved");
  });
</script>
<link rel="stylesheet" href="https://unpkg.com/alert-notify@2/dist/style.css" />
<script src="https://unpkg.com/alert-notify@2/dist/alert-notify.global.js"></script>
<script>
  AlertNotify.toast.success("Hello from CDN");
</script>

Dark mode & CSS variables

Set theme to light, dark, or system. System mode follows the OS, plus html.dark / data-theme="dark". Rebrand colors by overriding CSS variables in your own stylesheet.

// Dark mode
toast.config({ theme: "system" }); // OS + html.dark / data-theme
toast.config({ theme: "dark" });
toast.config({ theme: "light" });
toast.config({ richColors: true }); // soft tinted fills
/* your-app.css — after alert-notify/style.css */
.an-toaster {
  --an-bg: #ffffff;
  --an-fg: #0f172a;
  --an-muted: #64748b;
  --an-border: rgba(15, 23, 42, 0.1);

  --an-success: #16a34a;
  --an-error: #e11d48;
  --an-warning: #ca8a04;
  --an-info: #2563eb;

  /* Soft rich fills */
  --an-success-bg: #ecfdf5;
  --an-success-border: #a7f3d0;
  --an-error-bg: #fff1f2;
  --an-error-border: #fecdd3;
  --an-warning-bg: #fffbeb;
  --an-warning-border: #fde68a;
  --an-info-bg: #eff6ff;
  --an-info-border: #bfdbfe;
}

.an-toaster[data-theme="dark"] {
  --an-bg: #1e293b;
  --an-fg: #f8fafc;
  --an-success: #4ade80;
  --an-error: #fb7185;
  --an-warning: #facc15;
  --an-info: #60a5fa;
  --an-success-bg: #14532d;
  --an-error-bg: #4c0519;
  --an-warning-bg: #422006;
  --an-info-bg: #1e3a8a;
}

Exports

import {
  toast,
  createToaster,
} from "alert-notify";

import { Toaster } from "alert-notify/react"; // optional
import { Toaster } from "alert-notify/vue";   // optional
import Toaster from "alert-notify/svelte";   // optional
import "alert-notify/style.css";

Alternative to toastify, Sonner, hot-toast & react-alert

If you landed here searching for react toast, toastify, tostify, react-toastify, react-hot-toast, Sonner, react-alert, notistack, or a React notification / snackbar library — alert-notify is built for that search, with a smaller footprint and no React-only lock-in.

You might knowWhy people switch
react-toastify / toastifyPopular React toastify stack; larger bundle. alert-notify targets the same toast UX in ~4–5KB with no framework lock-in.
react-hot-toastMinimal React toasts. alert-notify matches the imperative feel and stays usable outside React.
SonnerPolished React toasts. alert-notify is smaller and framework-agnostic if you ship Vue, Svelte, or vanilla too.
react-alert / react notificationsAlert and notification patterns for React. Use toast.success / toast.error / toast.info for the same messaging jobs.
notistack / snackbarsMaterial-style snackbars. alert-notify covers snackbar-like toasts with positions, actions, and stacking.

FAQ

Common questions about React toasts, toastify alternatives, and framework-agnostic notifications.

What is a good React toast notification library?

alert-notify is a tiny (~4.7KB gzip) toast notification library for React and every other framework. Call toast.success / toast.error from anywhere — no root provider. It is a lightweight alternative to react-toastify, react-hot-toast, Sonner, react-alert, and notistack.

Is alert-notify an alternative to react-toastify or toastify?

Yes. If you searched for react-toastify, toastify, or tostify, alert-notify covers the same job — success, error, warning, info, loading, and promise toasts — in a much smaller package with zero runtime dependencies and no React lock-in.

Can I use it instead of react-hot-toast or Sonner?

Yes. alert-notify is similar in spirit to react-hot-toast and Sonner (simple imperative API, stacking, rich colors) but works in React, Vue, Svelte, Angular, Astro, and plain HTML. Optional <Toaster /> wrappers exist for React, Vue, and Svelte.

Does it replace react-alert or other React notification / snackbar libs?

If you need react-alert style notifications, React snackbars, or general React notification toasts, alert-notify can replace them. Same patterns: success/error messages, actions like Undo, dismiss, and position control — without a required container.

Does it work without React?

Yes. The core is vanilla TypeScript. Use it from Vue, Svelte, Angular, Astro islands, or a CDN script tag. Framework packages only sync config props; the portal auto-mounts.

How do I install and show a toast?

npm install alert-notify, import alert-notify/style.css, then call toast.success("Saved") or toast.error("Failed"). No provider and no root portal component are required.