Never heard of react-toastify before? Go check the demo
I’m super excited about this release! The main focus was on customization, and my goal was to empower you (and myself) so you can fully personalize the look and feel for the notifications.
In short, react-toastify should be able to blend into any design system.
The stylesheet is now injected automatically, so you no longer need to import it. The CSS file is still exported by the library.
import { ToastContainer, toast } from 'react-toastify'; function App(){ const notify = () => toast("Wow so easy !"); return ( <div> <button onClick={notify}>Notify !</button> <ToastContainer /> </div> ); }
One of the top requests has been how to customize notifications. To be fair, until this release, it was quite challenging because it required users to override numerous CSS classes.
I’ve simplified the DOM structure of the notification by removing extraneous div elements, nested elements, etc... It’s a significant breaking change, but it’s truly worth the effort. I can confidently say that the library can now seamlessly integrate into any design system.
Below, I’ve implemented a couple of different designs using only Tailwind. I didn’t override a single CSS class from react-toastify ?!
Head to stackblitz to check the code.
How does it work in practice? On the left side, we have the old DOM structure vs the new one on the right side.
Thanks to those changes, nothing will interfere with your content.
Toastify__toast has some sensible default values(e.g., border-radius, shadow, etc...) that can be customized using css or by updating the associated css variables:
width: var(--toastify-toast-width); min-height: var(--toastify-toast-min-height); padding: var(--toastify-toast-padding); border-radius: var(--toastify-toast-bd-radius); box-shadow: var(--toastify-toast-shadow); max-height: var(--toastify-toast-max-height); font-family: var(--toastify-font-family);
Allowing a custom progress bar wasn’t on my to-do list at all while working on this release. But seeing how easy it is to customize notifications now, I couldn’t resist ?.
The best part is that you don’t have to compromise on features like autoClose, pauseOnHover,pauseOnFocusLoss, or even a controlled progress bar—it just works seamlessly for you.
Here is a small gist.
function App() { const notify = () => { toast(CustomComponent, { autoClose: 8000, // removes the built-in progress bar customProgressBar: true }); }; return ( <div> <button onClick={notify}>notify</button> <ToastContainer /> </div> ); } // isPaused is now available in your component // it tells you when to pause the animation: pauseOnHover, pauseOnFocusLoss etc... function CustomComponent({ isPaused, closeToast }: ToastContentProps) { return ( <div> <span>Hello</span> <MyCustomProgressBar isPaused={isPaused} onAnimationEnd={() => closeToast()} /> </div> ); }
Head to stackblitz for a live example.
ToastContainer and toast accept an ariaLabel prop(finally...). This is quite helpful for screen readers and also for testing.
For example, in cypress you could do cy.findByRole("alert", {name: "the aria label you specified"}).
import { ToastContainer, toast } from 'react-toastify'; function App(){ const notify = () => toast("Wow so easy !"); return ( <div> <button onClick={notify}>Notify !</button> <ToastContainer /> </div> ); }
If a notification is visible and the user presses alt t it will focus on the first notification allowing the user to use Tab to navigate through the different elements within the notification.
The hotKeys can be changed of course.
width: var(--toastify-toast-width); min-height: var(--toastify-toast-min-height); padding: var(--toastify-toast-padding); border-radius: var(--toastify-toast-bd-radius); box-shadow: var(--toastify-toast-shadow); max-height: var(--toastify-toast-max-height); font-family: var(--toastify-font-family);
Do you want to know whether the user closed the notification or if it closed automatically? Rest assured, this is now possible!
The signature of the onClose callback is now onClose(reason?: boolean | string) => void.
When the user closes the notification, the reason argument is equal to true. In the example below, I've named my argument
removedByUser to make the intent clear.
function App() { const notify = () => { toast(CustomComponent, { autoClose: 8000, // removes the built-in progress bar customProgressBar: true }); }; return ( <div> <button onClick={notify}>notify</button> <ToastContainer /> </div> ); } // isPaused is now available in your component // it tells you when to pause the animation: pauseOnHover, pauseOnFocusLoss etc... function CustomComponent({ isPaused, closeToast }: ToastContentProps) { return ( <div> <span>Hello</span> <MyCustomProgressBar isPaused={isPaused} onAnimationEnd={() => closeToast()} /> </div> ); }
If you are using a custom component for your notification, you might want more control over the reason, especially if it contains
multiple call to actions.
toast("hello", { ariaLabel: "something" })
Those hooks are unusable unless you deep dive in react-toastify source code to understand how to glue things together. This is not what I want for my users, it was a bad decision to expose them in the first place, I've learned a good lesson.
In hindsight, I should never have done this. The feature is practically not used. Below the new signature for each callback:
I'm gradually rewriting part of the documentation. I've created a collection on stackblitz, this way you can find all the examples in one place. I'll keep adding more examples as I go.
The above is the detailed content of React-toastify v- finally easy to customize. For more information, please follow other related articles on the PHP Chinese website!