Skip to content
4 April 2026Product DesignMicrocopyInteraction DesignReact

We replaced our toast library with 230 lines. The strings were the hard part.

Sonner is a good toast library. Our problem was not the library. It was what happened when someone tapped Save three times and received three identical confirmations climbing up the screen.

We replaced it with about 230 lines of React and Motion. The first version took a day. The wording and state rules took much longer.

One operation should own one notification

When the same action happens again, the system now updates the existing toast. It increments a count, gives the capsule a small pulse and restarts the dismissal timer. The user sees that every tap registered without having to read the same sentence three times.

9:41
100%
Saved
Duplicates merge with a count badge and pulse – never stack

The same rule made progress states simpler. A toast that begins as “Saving from clipboard…” keeps its identity and becomes “Saved”. It does not disappear so that another message can take its place. One object changes because one operation changed.

9:41
100%
Saving from clipboard…
Loading morphs into success – same capsule, no flicker

The words had to carry the state

Most success messages became short outcomes: “Saved”, “Copied”, “Removed”. A description appears only when it adds a useful consequence, such as where an item went or what changed next.

Delivery messages are different. “Your look is ready” can justify the possessive because the person waited for something made for them. An error needs an action when one exists. “Could not save this item” is only useful if the next line says whether to try again, wait or change something.

9:41
100%
Could not save this itemPlease try again.
Error with description – say what went wrong, offer a next step

Motion shows continuity

The pulse on a repeated save is not decoration. It shows that the existing object changed. The loading state cannot be dismissed because the operation is still running. Once the operation ends, the toast becomes draggable and can be flicked back towards the top edge it entered from.

9:41
100%
Look saved!
Drag upward to dismiss – try it

We kept a pill for short messages and let it expand when a description was necessary. Variants still distinguish success, error and branded moments, but colour never has to explain the message on its own.

Saved
success
Could not savePlease try again.
error
Your look is ready
brand

Why the custom system was worth it

The finished component is small because it does not try to solve every notification problem. It solves the ones our product actually had: repeated actions, operations that change state and messages whose wording needs to stay consistent.

The animation made the system feel coherent. The copy made it understandable. That turned out to be the harder part.