webdevpuneet.com

Toastify Notification Stack with Undo — Free HTML CSS JS Snippet

Toastify Notification Stack with Undo · Modals · Plain HTML, CSS & JS · Live preview

CategoryModals

Copy & paste

Source Code

<div class="tn-wrap">
  <div class="tn-title">Inbox</div>
  <ul class="tn-list" id="tnList"></ul>
  <p class="tn-hint">Deleting an email shows an undo toast for 5 seconds</p>
</div>

Extend with AI

Take This Snippet Further With AI

The AI prompt for this one is for Patreon supporters ($3 a month, 7 days free), along with a site with no ads. Supporters enter the passcode once and it is remembered in this browser.

· Become a supporter

What's included

Features

Genuinely reversible deletion
The data is not touched until the undo window expires.
Callback-driven permanence
Toastify's own timer completion is what finalizes the delete.
Real interactive toast content
A custom DOM node enables an actual clickable Undo button.
Independent per-item undo state
A pending map, not a single global "last deleted" slot.
Immediate visual feedback
The item disappears instantly, staged deletion happens after.
Correctly scoped click handling
The Undo button has its own listener, separate from the toast.

About this UI Snippet

Toastify Notification Stack with Undo — Deletion That Isn't Actually Immediate

Screenshot of the Toastify Notification Stack with Undo snippet rendered live

A real "undo delete" needs the delete to not actually happen yet — otherwise "undo" would need to somehow reverse a completed action, which is a much harder problem than simply not doing it in the first place. This snippet stages every delete behind a pending-state map and a toast's own timer, so Undo just means "never actually go through with it."

Deletion is staged in a pending map, not applied to the data immediately

Clicking delete adds the email's id to pendingDeletes and re-renders, which is what makes it disappear from the list right away — but the email is still sitting in the real EMAILS array the whole time. Nothing has actually been removed yet; only the render filter is currently hiding it.

Toastify's own callback is where deletion becomes real

Toastify's callback option runs when a toast's timer finishes and it's automatically dismissed — *not* when it's shown. This snippet's callback is the only place that actually splices the email out of the EMAILS array for good, which means the deletion only becomes permanent once the undo window has genuinely expired without being used.

Undo works by preventing that callback from mattering, not by reversing anything

Clicking "Undo" clears the pending flag, re-renders (bringing the email back into view), and calls toast.hideToast() to dismiss the toast early. Toastify's callback still isn't guaranteed to run in every version/path when a toast is manually hidden versus timing out naturally — but because the pending flag was already cleared and the render already restored the email, nothing else needs to happen for undo to be complete. There was never a real deletion to reverse.

A custom node instead of a text string is what allows a real Undo button

Toastify's basic text option only supports plain text content. Passing a pre-built node — a real DOM element containing both a message span and a button — is what makes an interactive, clickable Undo control inside the toast possible, with the button's own click listener attached directly to that node before the toast is even shown.

Reusing it

This staged-delete-plus-undo-window pattern generalizes to any reversible destructive action — archiving, removing a list item, discarding a draft — swap the specific data operations for whatever "delete" and "restore" actually mean for your data.

Step by step

How to Use

  1. 1
    Add the Toastify CDNLoad toastify.min.css and toastify.min.js before the snippet's JS runs.
  2. 2
    Paste HTML, CSS, and JSFive sample emails render in a list.
  3. 3
    Click the × on any emailIt disappears and an undo toast appears at the bottom.
  4. 4
    Click UNDO within 5 secondsThe email reappears in the list exactly where it was.
  5. 5
    Delete another email and waitAfter 5 seconds, the deletion becomes permanent.
  6. 6
    Delete several emails quicklyEach gets its own independent undo window.

Real-world uses

Common Use Cases

Email-style delete with undo
Stage a deletion behind a timer, so an Undo click cancels it before it ever becomes permanent, as in Gmail.
List and table row deletion
Support any destructive list action with a recovery window, using a pending map so each item has its own independent undo state.
File and document management
Pair with the SweetAlert2 confirmation dialog set for actions that deserve both a prompt and an undo.
Shopping cart removal
Let shoppers recover an accidentally removed item, with a clickable Undo built from a custom DOM node inside the toast.
Draft and note discarding
Make low-friction removal reversible, with Toastify's own timer completion callback finalising the delete only once the window expires.

Got questions?

Frequently Asked Questions

No — clicking delete only adds that email's id to a pendingDeletes tracking object and re-renders the list, which filters out anything in that pending state. The email object itself remains untouched in the real EMAILS array the entire time the undo toast is showing; nothing is actually removed from the underlying data until the undo window expires.

Toastify's callback option is a function that runs specifically when a toast's own timer completes and it dismisses itself naturally (not when it's shown, and not necessarily when manually hidden early). This snippet's callback is the only code that actually filters the email out of the real EMAILS array — meaning the deletion only becomes permanent once the 5-second undo window has fully elapsed without the user clicking Undo.

Since the email was never really removed from EMAILS — only hidden via the pendingDeletes flag — undo simply clears that flag, re-renders the list (which now shows the email again, reading from the same array it was always in), and hides the toast early. There's no data to restore or reverse, because the "deletion" was staged rather than applied from the start.

Toastify's basic text option can only display a plain string — it has no mechanism for embedding an interactive element like a button inside the toast. Passing a pre-built DOM node (containing both a text span and a real button element) via the node option is what makes it possible to have an actual clickable Undo control inside the toast, with its own click event listener attached to that button before the toast is shown.

Each deletion creates its own independent entry in pendingDeletes (keyed by that email's id) and its own separate Toastify instance with its own 5-second timer. This means deleting several emails quickly gives each one its own independent undo window and its own toast, rather than one deletion's undo accidentally affecting or canceling a different email's pending deletion.