Undo Snackbar
An undo prompt bar with a countdown progress ring that confirms the action automatically when time runs out.
A snackbar that pops up from the bottom after a destructive action, holding a message, an undo button, and an SVG ring countdown (five seconds by default): pressing undo cancels the action and reports through onUndo, while the countdown reaching zero fires onCommit to make the action take effect for real. The countdown pauses automatically on pointer hover or keyboard focus. You can wire it up directly with controlled props, or use useUndoSnackbar for ready-made state management.
Bring this into your project
Run this command in your project folder. The CLI adds the source and dependencies; then follow the usage example below.
npx webberui@latest add undo-snackbar.enPlayground
Tune the props live — the code snippet updates as you go, so you can dial in the look you want before copying it.
<UndoSnackbar/>
The complete example includes the preview layout and data. Install the component first, then paste this file into your project.
Installation
npx webberui@latest add https://webberui.com/r/undo-snackbar.en.jsonOr, once registries are configured in components.json, install it as @webberui/undo-snackbar.
Usage
import { UndoSnackbar, useUndoSnackbar } from "@/components/ui/undo-snackbar";
function Inbox() {
const { show, snackbarProps } = useUndoSnackbar({ duration: 5000 });
const handleDelete = (item: Item) => {
hideItem(item.id); // optimistically remove it from the screen first
show(`Deleted "${item.title}"`, {
onUndo: () => restoreItem(item.id), // undo pressed within five seconds → restore
onCommit: () => permanentlyDelete(item.id), // timed out → delete for real
});
};
return (
<>
{/* ...list... */}
<UndoSnackbar {...snackbarProps} />
</>
);
}You can also skip the hook and manage the open state yourself with controlled props, closing it inside onUndo / onCommit.
Props
UndoSnackbar
| Prop | Type | Default | Description |
|---|---|---|---|
open | boolean | — | Whether the snackbar is shown (controlled); close it inside onUndo / onCommit |
message | string | — | The snackbar message text |
duration | number | 5000 | Total countdown duration (milliseconds); reaching zero fires onCommit |
undoLabel | string | "Undo" | Text of the undo button — the built-in default is the meaning "Undo", so pass this prop to localize it |
onUndo | () => void | — | Called when undo is pressed: cancels the action and closes |
onCommit | () => void | — | Called when the countdown ends: the action takes effect for real |
resetKey | number | string | — | When showing the same message repeatedly, changing this value restarts the countdown |
positioning | "fixed" | "absolute" | "fixed" | Snaps to the bottom of the window or of the nearest positioned ancestor |
className | string | — | Forwarded to the snackbar panel |
useUndoSnackbar
| Item | Type | Description |
|---|---|---|
options.duration | number | Total countdown duration (milliseconds), default 5000 |
options.undoLabel | string | Text of the undo button |
show(message, handlers?) | function | Shows the snackbar and registers onUndo / onCommit; any pending action still outstanding is committed immediately first |
close() | function | Closes silently, firing no callback |
snackbarProps | UndoSnackbarProps | Spread straight into <UndoSnackbar {...snackbarProps} /> |
Accessibility
- The snackbar uses
role="status"andaria-live="polite", so the message is announced automatically by the screen reader when it appears - The countdown pauses on pointer hover or keyboard focus (tabbing to the undo button) and only resumes once you leave, guaranteeing enough time to react
- Undo is a native
<button>with full keyboard support and afocus-visiblefocus ring - The ring countdown and the remaining seconds are visual aids and are hidden from assistive technology (
aria-hidden) - When the user has "reduce motion" enabled at the system level, the enter and exit become a plain fade in / fade out with no offset or spring animation