Every React app needs toast notifications. So there are roughly a thousand toast libraries on npm.
I built another one. But this one has a robot.
Why though?
I was building a side project and dropped in react-toastify. Functional. Totally forgettable. Then tried sonner — cleaner, but still just a rectangle sliding in from the corner.
I wanted something that actually made users presents my persona on my site when something happened in the app. So I built robot-toast.
What started as a weekend experiment is now a full-featured, production-ready library at v2.1.5 — 21 published versions, a demo playground, tests, and actual downloads from people I don't know.
What makes it different
Most toast libraries compete on the same axis: bundle size, API ergonomics, animation smoothness. robot-toast does all of that, but the actual differentiator is that you can customize everything in your own way and bring personality to your product, and to get you a headsup, robot-toast comes with 16 robot variants.
It sounds gimmicky. It isn't. Here's why it works:
- Error states feel less brutal when a robot looks flustered instead of a red bar flashing
- Success feels genuinely rewarding when the robot waves
- Users notice and remember it — which matters for apps where UX polish is a competitive edge
The full feature set (v2)
npm install robot-toast
Basic usage
import { toast } from 'robot-toast';
import { wave } from 'robot-toast/robots';
toast('Hello world');
toast.success('Saved!');
toast.error('Something broke');
toast({ message: 'Custom robot!', robotVariant: wave });
16 tree-shakeable robot variants
Each robot is a separate subpath export. You only ship the ones you use — no dead SVG weight in your bundle.
You can also pass any custom SVG/PNG/GIF path:
toast({ message: 'Custom!', robotVariant: '/my-mascot.svg' });
toast.promise()
toast.promise(fetch('/api/save').then(r => r.json()), {
loading: 'Saving…',
success: (data) => `Saved as ${data.name}`,
error: (err) => `Failed: ${err.message}`,
});
One of my favourite patterns. Attach loading/success/error states to any promise in a single call. No managing state yourself.
Typewriter effect
toast({ message: 'Deploying your app…', typeSpeed: 30 });
The message types out character by character. I haven't seen this in any other toast library. Small touch, weirdly satisfying to watch.
Custom action buttons
toast({
message: 'File deleted',
buttons: [
{ label: 'Undo', onClick: () => restoreFile() },
{ label: 'Keep', onClick: () => {}, style: { color: 'gray' } },
],
});
No limit on number of buttons. Most libraries restrict you to one action and one cancel.
Full options
toast({
message: 'Notification text',
type: 'default' | 'info' | 'success' | 'warning' | 'error',
theme: 'light' | 'dark' | 'colored',
transition: 'bounce' | 'flip' | 'zoom' | 'slide',
position: 'top-left' | 'top-center' | 'top-right' |
'bottom-left' | 'bottom-center' | 'bottom-right',
autoClose: 5000 | false,
typeSpeed: 30,
hideProgressBar: false,
draggable: true,
pauseOnHover: true,
pauseOnFocusLoss: true,
nearScreen: true,
rtl: false,
style: { background: '...', color: '...' },
onOpen: () => {},
onClose: () => {},
});
Framework-agnostic core
The core library has no framework dependency. React is an optional peer dependency.
// Vanilla JS
import { toast } from 'robot-toast';
toast.success('Works anywhere');
// React hook
import { useRobotToast } from 'robot-toast/react';
function App() {
const toast = useRobotToast();
return <button onClick={() => toast.success('Saved!')}>Save</button>;
}
Works with React, Next.js, Vue, Angular, Svelte, vanilla JS — one install, no adapter packages.
Accessibility
This part I'm genuinely proud of:
-
error/warningtoasts:role="alert"+aria-live="assertive"— announced immediately - Other types:
role="status"+aria-live="polite"— announced at next opportunity -
aria-atomic="true"— full message re-announced on update - Labeled close button for screen readers
Most indie toast libraries treat a11y as an afterthought. I didn't want to do that.
Comparison with the popular ones
| robot-toast | Sonner | react-toastify | react-hot-toast | |
|---|---|---|---|---|
| Framework agnostic | ✅ | ❌ | ❌ | ❌ |
| Animated character | ✅ | ❌ | ❌ | ❌ |
| Typewriter effect | ✅ | ❌ | ❌ | ❌ |
| Unlimited buttons | ✅ | ❌ | ✅ | ❌ |
| toast.promise() | ✅ | ✅ | ✅ | ✅ |
| Zero prod deps | ✅ | ✅ | ✅ | ✅ |
| Tree-shakeable assets | ✅ | N/A | N/A | N/A |
| Full a11y | ✅ | ✅ | ✅ | partial |
Sonner is the dominant player right now and it deserves to be — the stacking animation and shadcn integration are excellent. robot-toast isn't trying to replace it. It's for the apps where personality matters.
Programmatic control
const id = toast('Working…');
// Update it
toast.closeById(id);
// Dismiss everything
toast.closeAll();
Try it
- Demo & playground: robot-toast.vercel.app
- npm: npmjs.com/package/robot-toast
- GitHub: github.com/Pratham2703005/robot-toast-package
npm install robot-toast
If you use it, drop a comment — I'm genuinely curious what people build with it. And if something's broken or missing, open an issue. v2 exists because of feedback on v1.


Top comments (0)