Undo Toast

Runs actions optimistically and commits only after an undo window, so a mistake can be taken back without an "Are you sure?".

StopsDeleted item gone with no undo

Installation

pnpm dlx shadcn@latest add https://bollard-ui.vercel.app/r/undo-toast.json

The files land in your project. They're yours to edit.

Usage

undo-toast-usage.tsx
import { UndoToaster, undoable } from "@/components/ui/undo-toast"

<UndoToaster className="static inset-auto mx-0 max-w-none px-0" />

What it catches

  • Regretted actions, undone before onCommit runs
  • Countdown paused while hovered, focused or the tab is hidden
  • Leaving the page, which flushes pending commits
  • Failed commits, rolled back with a notice

Props

UndoToaster props
PropTypeDefault
hotkey

Bind Ctrl+Z / ⌘+Z to undo the newest pending action.

booleantrue
undoLabel

Label of each toast's undo button.

string"Undo"
failedText

Shown when a commit fails and is rolled back.

React.ReactNode"That didn't go through, so it was put back."
dismissLabel

Accessible label of the button that closes a failure notice.

string"Dismiss"

* required. Also accepts the native props of <section> (className, aria-*, data-*…), passed through to it.

Accessibility

  • Toast region has an aria-label and polite live updates; failures use role=alert
  • Undo button has an aria-label with the message and aria-keyshortcuts
  • Ctrl/⌘+Z triggers undo when hotkey is on
  • Countdown ring respects reduced motion

Only what the source does. Test with your own screen reader and content before shipping.

Limitations

  • Commits on pagehide can't be awaited; use fetch keepalive or sendBeacon
  • If the tab crashes, a pending commit may never run
  • Other users may see the optimistic state only after commit

What it stops

Deleted item gone with no undo

Also known as

undo · snackbar · toast · sonner · optimistic update · ctrl+z · gmail undo · archive

Dependencies

Pairs well with