Decision. Reach for Sonner ⭐ 12.6k unless you have a reason not to — it is what
shadcn add sonnerinstalls, it has zero runtime dependencies, and at 41.4M weekly npm installs it is now an order of magnitude more installed than anything else in this category [1] [2]. Reach for react-toastify ⭐ 13.4k when you need a deep, configurable feature surface (custom progress bars, notification centre, CSP nonce) and the most recent release cadence — v11.1.0 shipped April 2026 [3]. Reach for react-hot-toast ⭐ 11k when bundle size dominates (4.7 kB gz, roughly half of everything else) [4]. If you already ship Mantine, Chakra v3 or Base UI, use the in-house toaster — it costs ~0 marginal bytes. notistack ⭐ 4.1k is the one to avoid for greenfield: no npm release since January 2025 [5].
All numbers below were fetched live on 2026-07-13 (npm registry, npm downloads API, Bundlephobia, GitHub). Star counts and sizes shift; the ledger records what was measured.
At a glance
| Library | ⭐ Stars | Weekly installs | min+gzip | Runtime deps | Latest release | Open issues | React 19 |
|---|---|---|---|---|---|---|---|
| Sonner [6] | ⭐ 12.6k | 41.4M [1] | 9.2 kB (33.4 kB min) [7] | 0 [1] | 2.0.7 — 2025-08-02 [1] | 52 [8] | ✓ peer ^18 \|\| ^19 [1] |
| react-toastify [9] | ⭐ 13.4k | 4.0M [10] | 9.5 kB (33.6 kB min) [11] | 1 (clsx) [10] |
11.1.0 — 2026-04-19 [3] | 72 [12] | ✓ explicit v11 fix [13] |
| react-hot-toast [14] | ⭐ 11k | 3.4M [15] | 4.7 kB (11.9 kB min) [4] | 2 (goober, csstype) [15] |
2.6.0 — 2025-08-15 [16] | ⚠ 115 [17] | ✓ types fixed in 2.5.2 [16] |
| notistack [18] | ⭐ 4.1k | 1.4M [5] | 8.2 kB (23.4 kB min) [19] | 2 (clsx, goober) [5] |
⚠ 3.0.2 — 2025-01-18 [5] | 53 [20] | ✓ peer allows ^19 [5] |
| @mantine/notifications [21] | ⭐ 31k (Mantine) | 741k [41] | 5.5 kB (+ @mantine/core) [22] |
peer: @mantine/core |
9.4.1 — 2026-06-28 [22] | — | ✓ |
| Chakra UI v3 Toaster [23] | ⭐ 41k (Chakra) | — | part of @chakra-ui/react 3.36.0 (293 kB gz whole lib, tree-shaken) [24] |
Ark UI | 3.36.0 — 2026-06-10 [24] | — | ✓ |
| MUI Snackbar [25] | ⭐ 99k (MUI) | — | part of @mui/material 9.2.0 (146.6 kB gz whole lib) [26] |
— | 9.2.0 — 2026-07-03 [26] | — | ✓ |
| Base UI Toast [27] | ⭐ 10k (Base UI) | 6.2M (@base-ui/react) [28] |
part of @base-ui/react 1.6.0 (145 kB gz whole lib) [28] |
— | 1.6.0 — 2026-06-18 [28] | — | ✓ |
The install gap is the headline number of 2026. Sonner is not “a bit more popular” than react-toastify — it is ~10× more installed per week (41.4M vs 4.0M) [1] [10], because every project scaffolded through shadcn/ui ⭐ 119k pulls it in: shadcn’s own toast component is formally deprecated in favour of Sonner [29] [30]. Treat downloads as an install-graph signal, not a popularity vote — but the install graph is what determines how much Stack Overflow, LLM training data and third-party wrappers exist for a library.
API surface and ergonomics
All four standalone libraries converge on the same shape: mount one container component at the app root, then call an imperative toast() from anywhere — no context, no prop drilling, callable from event handlers, catch blocks, or non-React code.
| Container | Call site | |
|---|---|---|
| Sonner | <Toaster /> [31] |
toast('msg'), toast.success/error/warning/info/promise/custom [31] |
| react-toastify | <ToastContainer /> [32] |
toast('msg', {...}), toast.success/error/…/promise [32] |
| react-hot-toast | <Toaster /> [33] |
toast(), toast.promise, plus useToaster() / useToasterStore() headless hooks [33] |
| notistack | <SnackbarProvider> wrapper |
enqueueSnackbar() / useSnackbar() |
| Mantine | <Notifications /> inside MantineProvider [34] |
notifications.show/hide/update/clean [34] |
| Chakra v3 | <Toaster /> + createToaster() [35] |
toaster.create/update/dismiss/promise [35] |
| Base UI | <Toast.Provider> + <Toast.Viewport> [36] |
useToastManager().add/update/close/promise, or a global manager via Toast.createToastManager() [36] |
| MUI Snackbar | none | ⚠ declarative only — you hold open state yourself [37] |
MUI Snackbar is the outlier and the reason notistack exists at all: it renders one snackbar bound to an open prop, has no queue, and the MUI docs themselves point at notistack for stacking — “With an imperative API, notistack lets you vertically stack multiple Snackbars without having to handle their open and close states” [37]. If you are on MUI and want toasts, you are choosing between hand-rolling a queue, adopting notistack (see maintenance caveat below), or dropping Sonner in next to MUI — Sonner has no MUI coupling.
Feature matrix
| Feature | Sonner | react-toastify | react-hot-toast | notistack | Mantine | Chakra v3 | Base UI |
|---|---|---|---|---|---|---|---|
toast.promise() (loading→success/error) |
✓ [31] | ✓ [32] | ✓ [33] | ✗ (manual update) |
✗ (manual notifications.update) [34] |
✓ toaster.promise [35] |
✓ .promise() [36] |
| Arbitrary JSX content | ✓ toast.custom [31] |
✓ “bring your own component” [32] | ✓ toast.custom [33] |
✓ content |
~ (Styles API, not free JSX) [34] | ✓ composable subcomponents [35] | ✓ fully composable parts [36] |
| Headless / unstyled mode | ✓ headless option [31] | ~ (v11 simplified DOM, CSS overridable) [13] | ✓ useToaster() [33] |
~ | ✗ | ~ | ✓ unstyled by design [36] |
| Visible-count cap / queue | ✓ visibleToasts [31] |
✓ limit [32] |
✓ (per-type limits) | ✓ maxSnack |
✓ limit + FIFO queue + priority [34] |
✓ max, overlap [35] |
✓ [36] |
| Stack-and-expand-on-hover UX | ✓ expand [31] |
✗ (list) | ✗ (list) | ✗ (list) | ✗ | ✓ overlap [35] |
✓ (CSS-var stacking) [36] |
| Update an existing toast by id | ✓ | ✓ | ✓ | ✓ | ✓ notifications.update [34] |
✓ [35] | ✓ (re-add with same id) [36] |
| Multiple independent toasters | ~ | ✓ (containerId) | ✓ added in 2.6.0 [16] | ✗ | ✗ | ✓ (multiple createToaster) [35] |
✓ |
| Zero CSS import needed | ✓ | ✓ since v11 — style tag is injected [13] | ✓ (goober CSS-in-JS) | ✓ (goober) | ⚠ must import @mantine/notifications/styles.css [34] |
✓ | ✓ (you write the CSS) |
| CSP nonce support | ~ | ✓ nonce prop (11.1.0) [3] |
~ | ~ | ✓ (Mantine-wide) | ✓ | ✓ |
| Swipe-to-dismiss | ✓ [31] | ✓ (drag) [3] | ✗ | ✗ | ✗ | ✓ | ✓ [36] |
TypeScript. All seven are TS-native and ship their own declarations — none needs @types/*. Sonner and react-hot-toast are written in TS with fully typed toast.* overloads; react-hot-toast explicitly swapped the deprecated global JSX.Element type for React.ReactElement in 2.5.2, which is exactly the change React 19’s type packages force [16]. react-toastify v11 removed the useToastContainer / useToast hooks from the public surface, so old typed wrappers around them break on upgrade [13].
Accessibility. All of them render an ARIA live region, so this axis is rarely the deciding factor — but it is not free. Sonner’s 4s default auto-dismiss is below what WCAG 2.2.1 (Timing Adjustable) implies for slow readers; raise the Toaster duration if a11y is audited [38]. react-toastify v11 added an ariaLabel prop and an alt+t keyboard shortcut to focus the notification region [13]; Base UI Toast uses F6 to jump to the viewport landmark and configurable low/high live-region priority [36]. Radix’s own Toast primitive has an open, unresolved report that toasts are not announced because the live region resolves to aria-live="off" — a reason to prefer Sonner over hand-rolled Radix toasts even inside a Radix codebase [39].
Maintenance health — the real differentiator
| Library | Last npm release | Last commit pushed | Read |
|---|---|---|---|
| react-toastify | 2026-04-19 (11.1.0) [3] | 2026-04-19 [9] | Actively released. Bug-fix-and-feature release only 3 months ago; 72 open issues on a 13.4k-star repo is normal load. |
| Sonner | 2025-08-02 (2.0.7) [1] | 2025-12-23 [6] | Quiet but not dead. ~11 months without a release, ~7 without a commit — feature-complete single-maintainer project, 52 open issues. ⚠ Bus factor is the risk, not bugs. |
| react-hot-toast | 2025-08-15 (2.6.0) [16] | 2025-08-16 [14] | Slow. ⚠ 115 open issues — highest absolute count here, and the repo has been untouched for ~11 months. Snyk still grades maintenance “Sustainable” on release cadence [40]. |
| notistack | ⚠ 2025-01-18 (3.0.2) [5] | 2026-03-31 [18] | Effectively legacy. 18 months without a published version. It still works (peer deps admit React 19, v3 dropped its MUI dependency and now ships on goober), and 1.4M weekly installs are mostly existing MUI codebases. Not a greenfield pick. |
| Mantine / Chakra / MUI / Base UI | 2026-06-28 / 2026-06-10 / 2026-07-03 / 2026-06-18 [22] [24] [26] [28] | this month | Backed by the design system’s release train — the toaster gets maintained as long as the design system does. |
Note the inversion of the popularity narrative: the library everyone installs (Sonner) has the quietest repo, and the library the blogosphere calls legacy (react-toastify) has the newest release. Neither fact should flip your decision on its own — a toast library is a small, finished problem — but if you need a fix landed upstream this quarter, react-toastify is the one whose maintainer is currently shipping.
Design-system natives: use them if you already pay for them
- Mantine —
notifications.show()from anywhere,limitwith a real FIFO queue and apriorityfield that can bump a notification into a visible slot ahead of older ones;notifications.update()covers the loading→done pattern manually since there is nopromise()helper. ⚠ It is the only option here that silently misbehaves without a CSS import (@mantine/notifications/styles.css, after core styles) [34]. +5.5 kB gz on top of@mantine/core[22]. - Chakra UI v3 —
createToaster()+toaster.create(); the most complete built-in of the four:toaster.promise(),max,overlapstacking,pauseOnPageIdle, composableTitle/Description/ActionTriggerparts, built on Ark UI [35]. Sensible only if Chakra is already your system —@chakra-ui/reactis 293 kB gz as a whole package (tree-shakeable, but the design-system tax is real) [24]. - MUI — Snackbar is a controlled component, not a toast system [37]. Pair with notistack (aging) or bolt Sonner on.
- shadcn/ui — there is no shadcn toast any more. The
toastcomponent page carries “The toast component has been deprecated. Use the sonner component instead.” [29], tracked in issue #7120 [30];sonneris now a first-class shadcn component with a pre-themed<Toaster />[2]. This single decision is what produced Sonner’s install numbers. - Base UI (the MUI team’s headless successor to Radix) — Toast is a genuine competitor now that Base UI is stable:
useToastManager()withadd/update/close/promise, acreateToastManager()for firing toasts outside React, swipe-to-dismiss, F6 landmark navigation, fully unstyled [36].@base-ui/reactreached 1.6.0 in June 2026 and does 6.2M weekly installs [28]. Pick it when you want to own every pixel and are already headless-first; skip it if you just want a toast that looks good today.
Reach for X when Y
| When… | Reach for |
|---|---|
| Greenfield React app, no strong design system, you want good defaults in 10 minutes | Sonner — 0 deps, 9.2 kB, toast.promise, stack-and-expand, shadcn-native [7] [2] |
| You use shadcn/ui | Sonner — there is no alternative in-system; toast is deprecated [29] |
| Bundle budget is the hard constraint (marketing site, embed, widget) | react-hot-toast — 4.7 kB gz, ~half of Sonner; ⚠ accept a slow-moving repo [4] [17] |
| You need deep customisation (custom progress bar, notification centre, CSP nonce, containerId routing) or you want the maintainer who is actually shipping | react-toastify v11 [13] [3] |
| You already ship Mantine or Chakra v3 | the built-in toaster — ~0 marginal bytes, matches your theme [34] [35] |
| You already ship MUI | Sonner alongside MUI, or notistack only if you’re already on it — MUI’s Snackbar has no queue [37] |
| Headless-first codebase, you style everything | Base UI Toast [36] |
| Existing notistack codebase | Stay — it works on React 19 — but ⚠ plan a Sonner migration; no release since Jan 2025 [5] |
| Greenfield + notistack | Don’t. |
Migrating away from a toast library is a mechanical find-and-replace of toast() call sites plus one root component — the switching cost is close to zero, which is exactly why you should not agonise over this decision. Take Sonner; revisit if a constraint bites.