The queue owns ordering, deduplication, eviction and timers. Rendering is yours - it returns a list and never an opinion about what a toast looks like.
- Nothing queued. Errors stay until dismissed; the rest fade after 5s.
Press "Retry" repeatedly: it replaces in place instead of stacking. Press "Error": it stays while the others fade.
Installation
Adds the package and prints the import to use. Append --copy to write the source into your project instead.
enigma add notificationsInstalls with your project's own package manager - npm, pnpm, yarn or bun - read from its packageManager field or its lockfile.
1 Install the dependencies
2 Use it
Import from @enigmax/primitives/react.
The queue renders nothing. Point it at whatever toaster you already have, or copy the
Tailwind recipe enigma add notifications --copy writes.
Vanilla
import { createNotifications } from "@enigmax/primitives";
const queue = createNotifications({ max: 4, duration: 5000 });
queue.notify({ key: "sync", title: "Retrying", tone: "warning" });
React
import { useNotifications } from "@enigmax/primitives/react";
const { items, notify, dismiss, pause, resume } = useNotifications();
Bind pause / resume to the stack’s pointer enter and leave, and nothing dismisses itself while a visitor is reading it.
The behaviour worth not rewriting
- A repeated
keyreplaces in place, so a retry loop does not build a wall of identical messages. - Errors stay until dismissed by default; everything else self-dismisses. Configurable through
stickyTones. - Over
max, the oldest dismissable notification makes room. A sticky error is never silently evicted - the one message the visitor most needs is the one a naive queue drops. pause()holds the remaining time rather than running it, and a hidden tab pauses automatically. A timer that keeps counting in the background fires the moment the visitor comes back, and they never see the message.
Notification shape
| Field | Meaning |
|---|---|
key |
Optional. Reuses the slot of a live notification with the same key. |
title / body |
The text. body is optional. |
tone |
info, success, warning, error. |
duration |
ms before self-dismissal. Infinity keeps it until dismissed. |
data |
Anything the renderer needs: an action label, an href, an icon name. |