Description
Thanks for the great work on Sonner. I've been using it for a long time and really appreciate how seamless and reliable it is out of the box.
For a recent project, I decided to go beyond the defaults and deeply customize Sonner’s appearance and behavior. I wanted to share some experience insights from that process, as I ran into a few challenges that I think could be worth considering for future improvements.
-
Overriding styles on the default Toaster
My first approach was to use the Toaster component and override styles directly. While this technically works, I often found myself adding redundant or even "nullifying" utility classes to undo the default styles. This is partly due to the lack of class merging utilities like clsx or tailwind-merge, which makes precise customization more cumbersome than it should be. -
Then i tried to use unstyled=true. And then i git the point of some of internal elements not being reachable directly.
-
Using a custom toast component
Next, I tried building a fully custom toast component. Visually, this gave me what I wanted, but it came with trade-offs:
I lost access to some of the built-in methods, like .promise, which are pretty valuable.
More critically, certain fundamental aesthetic behaviors didn’t translate well. For example: stacking a short toast on top of a long one no longer behaves as expected. See this repro