Variants
pushAlert.info / .success / .warning / .errorDedup by content hash
Spam the button: the same message replaces in place instead of stackingSpinner → result (replace)
Sonner can't mutate a live duration, so the spinner toast is replaced by its result under the same idpushAlert.promise
One call: spinner while pending, replaced by the outcome under the same idCustom controls
options.controls adds action buttons; they inherit the alert's content colorPosition
The stack sits bottom-right by default now; the Toasts mount takes any Sonner positionThis page mounts <Toasts /> with the default: fire any toast above and watch the bottom-right corner.
Persistent + copyable
duration -1 stays until dismissed; error toasts get a copy button by defaultToasts host
Mounted once in the app shell; every pushAlert on this page renders through it<Toasts /> // this gallery mounts it in app/layout.tsxuseAlertToast
The pusher as a hook: consumers depend on a stable interface they can stub, not on Sonner directlyStyling slots
Every className the component exposes, and what it reaches- className
- the toast card
- descriptionClassName
- the message region