DEV Community

Pratham Kumar
Pratham Kumar

Posted on

I Built a Toast Library Where a Robot Delivers Your Notifications 🤖

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.

Using robot-toast is Fun


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
Enter fullscreen mode Exit fullscreen mode

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 });
Enter fullscreen mode Exit fullscreen mode

16 tree-shakeable robot variants

16 In built Robots: wave, base, base2, success, error,<br>
  angry, angry2, shock, think, search,<br>
  loading, sleep, headPalm, typing,<br>
  validation, validation2.

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' });
Enter fullscreen mode Exit fullscreen mode

toast.promise()

toast.promise(fetch('/api/save').then(r => r.json()), {
  loading: 'Saving…',
  success: (data) => `Saved as ${data.name}`,
  error: (err) => `Failed: ${err.message}`,
});
Enter fullscreen mode Exit fullscreen mode

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 });
Enter fullscreen mode Exit fullscreen mode

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' } },
  ],
});
Enter fullscreen mode Exit fullscreen mode

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: () => {},
});
Enter fullscreen mode Exit fullscreen mode

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>;
}
Enter fullscreen mode Exit fullscreen mode

Works with React, Next.js, Vue, Angular, Svelte, vanilla JS — one install, no adapter packages.


Accessibility

This part I'm genuinely proud of:

  • error / warning toasts: 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();
Enter fullscreen mode Exit fullscreen mode

Try it

npm install robot-toast
Enter fullscreen mode Exit fullscreen mode

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)