UNPKG

40.4 kBMarkdownView Raw
1# React-Toastify
2
3![Travis (.org)](https://img.shields.io/travis/fkhadra/react-toastify.svg?label=%F0%9F%9A%A7Build&style=for-the-badge)
4![npm](https://img.shields.io/npm/dm/react-toastify.svg?label=%E2%8F%ACdownloads&style=for-the-badge)
5![npm](https://img.shields.io/npm/v/react-toastify.svg?style=for-the-badge)
6![NPM](https://img.shields.io/npm/l/react-toastify.svg?label=%F0%9F%93%9Clicense&style=for-the-badge)
7![Coveralls github](https://img.shields.io/coveralls/github/fkhadra/react-toastify.svg?label=%E2%9B%B1coverage&style=for-the-badge)
8![React toastify](https://user-images.githubusercontent.com/5574267/35336500-e58f35b6-0118-11e8-800b-2da6594fc700.gif "React toastify")
9
10
11🎉 React-Toastify allow you to add notification to your app with ease. No more nonsense!
12
13 - [Demo](#demo)
14 - [Installation](#installation)
15 - [Features](#features)
16 - [Usage](#usage)
17 - [One component to rule them all](#one-component-to-rule-them-all)
18 - [One ToastContainer to render them](#one-toastcontainer-to-render-them)
19 - [What if I told you that the ToastContainer is optional](#what-if-i-told-you-that-the-toastcontainer-is-optional)
20 - [Multi container support](#multi-container-support)
21 - [Positioning toast](#positioning-toast)
22 - [Set autoclose delay or disable it](#set-autoclose-delay-or-disable-it)
23 - [Render a component](#render-a-component)
24 - [Remove a toast programmatically](#remove-a-toast-programmatically)
25 - [Usage with redux](#usage-with-redux)
26 - [Pause toast timer when the window loses focus](#pause-toast-timer-when-the-window-loses-focus)
27 - [Use a custom id](#use-a-custom-id)
28 - [Prevent duplicate](#prevent-duplicate)
29 - [Delay notification appearance](#delay-notification-appearance)
30 - [Use a controlled progress bar](#use-a-controlled-progress-bar)
31 - [Update a toast](#update-a-toast)
32 - [Basic example](#basic-example)
33 - [Update the content](#update-the-content)
34 - [Update the toast id](#update-the-toast-id)
35 - [Apply a transition](#apply-a-transition)
36 - [Reset option or inherit from ToastContainer](#reset-option-or-inherit-from-toastcontainer)
37 - [Define callback](#define-callback)
38 - [Listen for change](#listen-for-change)
39 - [Set a custom close button or simply remove it](#set-a-custom-close-button-or-simply-remove-it)
40 - [Override the default one](#override-the-default-one)
41 - [Define it per toast](#define-it-per-toast)
42 - [Remove it](#remove-it)
43 - [Add an undo option to a toast like google drive](#add-an-undo-option-to-a-toast-like-google-drive)
44 - [Replace the default transition](#replace-the-default-transition)
45 - [Define a custom enter and exit transition](#define-a-custom-enter-and-exit-transition)
46 - [Ease your life with the cssTransition helper](#ease-your-life-with-the-csstransition-helper)
47 - [Different duration for enter and exit](#different-duration-for-enter-and-exit)
48 - [Handle transition based on the toast position](#handle-transition-based-on-the-toast-position)
49 - [Create a transition from scratch](#create-a-transition-from-scratch)
50 - [Swipe to remove](#swipe-to-remove)
51 - [Define the width percentage to remove the toast](#define-the-width-percentage-to-remove-the-toast)
52 - [Disable it](#disable-it)
53 - [Le style](#le-style)
54 - [style with css classes](#style-with-css-classes)
55 - [style with glamor](#style-with-glamor)
56 - [Define style globally](#define-style-globally)
57 - [Right to left support](#right-to-left-support)
58 - [Mobile](#mobile)
59 - [Api](#api)
60 - [ToastContainer](#toastcontainer)
61 - [toast](#toast)
62 - [cssTransition](#csstransition)
63 - [Browser Support](#browser-support)
64 - [Release Notes](#release-notes)
65 - [Contribute](#contribute)
66 - [License](#license)
67
68## Demo
69
70[A demo is worth a thousand words](https://fkhadra.github.io/react-toastify/)
71
72## Installation
73
74```
75$ npm install --save react-toastify
76$ yarn add react-toastify
77```
78
79> RC.5 `useLazyContainer has been removed. The lazy container is opt-in`
80
81## Features
82
83- Easy to setup for real, you can make it work in less than 10sec!
84- Super easy to customize
85- RTL support
86- Swipe to close 👌
87- Can display a react component inside the toast!
88- Has ```onOpen``` and ```onClose``` hooks. Both can access the props passed to the react component rendered inside the toast
89- Can remove a toast programmatically
90- Define behavior per toast
91- Pause toast when window loses focus 👁
92- Fancy progress bar to display the remaining time
93- Possibility to update a toast
94- You can controll the progress bar a la npgrogress 😲
95- Starting v5 the `ToastContainer` is optional if you want to 😎
96
97## Usage
98
99### One component to rule them all
100
101#### One ToastContainer to render them
102
103The toasts inherit ToastContainer's props. **Props defined on toast supersede ToastContainer's props.**
104
105```javascript
106 import React, { Component } from 'react';
107 import { ToastContainer, toast } from 'react-toastify';
108 import 'react-toastify/dist/ReactToastify.css';
109 // minified version is also included
110 // import 'react-toastify/dist/ReactToastify.min.css';
111
112 class App extends Component {
113 notify = () => toast("Wow so easy !");
114
115 render(){
116 return (
117 <div>
118 <button onClick={this.notify}>Notify !</button>
119 <ToastContainer />
120 </div>
121 );
122 }
123 }
124```
125
126Remember to render the `ToastContainer` *once* in your application tree.
127If you can't figure out where to put it, rendering it in the application root would be the best bet.
128
129#### What if I told you that the ToastContainer is optional
130
131```javascript
132 import React, { Component } from 'react';
133 import { toast } from 'react-toastify';
134 import 'react-toastify/dist/ReactToastify.css';
135
136 // Call it once in your app. At the root of your app is the best place
137 toast.configure()
138
139 const App = () => {
140 const notify = () => toast("Wow so easy !");
141
142 return <button onClick={notify}>Notify !</button>;
143 }
144```
145
146The library will mount a `ToastContainer` for you if none is mounted.
147
148
149#### Configure the ToastContainer when it is mounted on demand
150
151The configure function accept the same props as the ToastContainer. As soon as the container is
152rendered call to configure will have no effect.
153
154```js
155toast.configure({
156 autoClose: 8000,
157 draggable: false,
158 //etc you get the idea
159});
160```
161
162
163#### Multi container support
164
165To enable multiple container support, you have to pass `enableMultiContainer` and specify a `containerId` and use it in
166each toast, to do so add `containerId` to the toast's options object.
167
168
169
170Note: adding `enableMultiContainer` prop to the `<ToastContainer/ >` will:
171- Check each toast to verify if its `containerId` match the container `containerId` so it can be rendered.
172- Ensure not to render any `toast` that has `containerId`.
173- Render any toast if both the `toast` and `<ToastContainer/ >` does not include `containerId` and `containerId` respectively.
174
175A simple example to demonstrate multi toast container capability.
176
177- Notify A button will show a toast on the bottom left.
178- Notify B button will show a toast on the top right.
179
180```javascript
181 import React, { Component } from 'react';
182 import { ToastContainer, toast } from 'react-toastify';
183 import 'react-toastify/dist/ReactToastify.css';
184
185
186 class App extends Component {
187 notifyA = () => toast('Wow so easy !', {containerId: 'A'});
188 notifyB = () => toast('Wow so easy !', {containerId: 'B'});
189
190 render(){
191 return (
192 <div>
193 <ToastContainer enableMultiContainer containerId={'A'} position={toast.POSITION.BOTTOM_LEFT} />
194 <ToastContainer enableMultiContainer containerId={'B'} position={toast.POSITION.TOP_RIGHT} />
195
196 <button onClick={this.notifyA}>Notify A !</button>
197 <button onClick={this.notifyB}>Notify B !</button>
198 </div>
199 );
200 }
201 }
202
203```
204
205
206### Positioning toast
207
208By default, all the toasts will be positioned on the top right of your browser. If a position is set on a `toast`, the one defined on ToastContainer will be replaced.
209
210The following values are allowed: **top-right, top-center, top-left, bottom-right, bottom-center, bottom-left**
211
212For convenience, `toast` expose a POSITION property to avoid any typo.
213
214```javascript
215 // toast.POSITION.TOP_LEFT, toast.POSITION.TOP_RIGHT, toast.POSITION.TOP_CENTER
216 // toast.POSITION.BOTTOM_LEFT,toast.POSITION.BOTTOM_RIGHT, toast.POSITION.BOTTOM_CENTER
217
218 import React, { Component } from 'react';
219 import { toast } from 'react-toastify';
220
221 class Position extends Component {
222 notify = () => {
223 toast("Default Notification !");
224
225 toast.success("Success Notification !", {
226 position: toast.POSITION.TOP_CENTER
227 });
228
229 toast.error("Error Notification !", {
230 position: toast.POSITION.TOP_LEFT
231 });
232
233 toast.warn("Warning Notification !", {
234 position: toast.POSITION.BOTTOM_LEFT
235 });
236
237 toast.info("Info Notification !", {
238 position: toast.POSITION.BOTTOM_CENTER
239 });
240
241 toast("Custom Style Notification with css class!", {
242 position: toast.POSITION.BOTTOM_RIGHT,
243 className: 'foo-bar'
244 });
245 };
246
247 render(){
248 return <button onClick={this.notify}>Notify</button>;
249 }
250 }
251```
252
253### Set autoclose delay or disable it
254
255- Set the default delay
256
257```js
258 import React from 'react';
259 import { ToastContainer } from 'react-toastify';
260
261 // close toast after 8 seconds
262 const App = () => (
263 <ToastContainer autoClose={8000} />
264 );
265```
266
267- Set the delay per toast for more control
268
269```js
270 import React from 'react';
271 import { ToastContainer, toast } from 'react-toastify';
272
273 class App extends Component {
274 closeAfter15 = () => toast("YOLO", { autoClose: 15000 });
275
276 closeAfter7 = () => toast("7 Kingdoms", { autoClose: 7000 });
277
278 render(){
279 return (
280 <div>
281 <button onClick={this.closeAfter15}>Close after 15 seconds</button>
282 <button onClick={this.closeAfter7}>Close after 7 seconds</button>
283 <ToastContainer autoClose={8000} />
284 </div>
285 );
286 }
287 }
288```
289
290- Disable it by default
291
292```js
293 <ToastContainer autoClose={false} />
294```
295
296- Disable it per toast
297
298```js
299 toast("hello", {
300 autoClose: false
301 })
302```
303
304### Render a component
305
306When you render a component, a `closeToast` function is passed as a props. That way you can close the toast on user interaction for example.
307
308```js
309import React from 'react';
310import { ToastContainer, toast } from "react-toastify";
311
312const Msg = ({ closeToast }) => (
313 <div>
314 Lorem ipsum dolor
315 <button>Retry</button>
316 <button onClick={closeToast}>Close</button>
317 </div>
318)
319
320const App = () => (
321 <div>
322 <button onClick={() => toast(<Msg />)}>Hello 😀</button>
323 <ToastContainer />
324 </div>
325);
326```
327
328You can also render a component using a function. More or less like a "render props":
329
330```js
331toast(({ closeToast }) => <div>Functional swag 😎</div>);
332```
333
334### Remove a toast programmatically
335
336An id is returned each time you display a toast, use it to remove a given toast programmatically by calling ```toast.dismiss(id)```
337
338Without args, all the displayed toasts will be removed.
339
340```javascript
341 import React, { Component } from 'react';
342 import { toast } from 'react-toastify';
343
344 class Example extends Component {
345 toastId = null;
346
347 notify = () => this.toastId = toast("Lorem ipsum dolor");
348
349 dismiss = () => toast.dismiss(this.toastId);
350
351 dismissAll = () => toast.dismiss();
352
353 render(){
354 return (
355 <div>
356 <button onClick={this.notify}>Notify</button>
357 <button onClick={this.dismiss}>Dismiss</button>
358 <button onClick={this.dismissAll}>Dismiss All</button>
359 </div>
360 );
361 }
362 }
363```
364
365### Usage with redux
366
367"Talk is cheap. Show me the code"
368
369[![Edit react+redux+react-toastify](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/2485wxy78j)
370
371### Pause toast timer when the window loses focus
372
373The default behavior is to pause the toast timer whenever the window loses focus. You can opt-out by setting the `pauseOnFocusLoss` props to false:
374
375```js
376// Opt-out for all toast
377<ToastContainer pauseOnFocusLoss={false} />
378
379// Opt-out per toast
380toast('Hello', {
381 pauseOnFocusLoss: false
382})
383```
384
385### Use a custom id
386
387A custom `toastId` can be used to replace the one generated. You can use a `number` or a `string`.
388
389```javascript
390 import React, { Component } from 'react';
391 import { toast } from 'react-toastify';
392
393 class Example extends Component {
394 notify = () => {
395 toast("I cannot be duplicated !", {
396 toastId: 13
397 });
398 }
399
400 render(){
401 return (
402 <div>
403 <button onClick={this.notify}>Notify</button>
404 </div>
405 );
406 }
407 }
408```
409
410### Prevent duplicate
411
412To prevent duplicates, you can check if a given toast is active by calling `toast.isActive(id)` like the snippet below. Or, you can use a custom `toastId`:
413
414```javascript
415 import React, { Component } from 'react';
416 import { toast } from 'react-toastify';
417
418 class Example extends Component {
419 toastId = null;
420 customToastId = 'xxx-yyy';
421
422 notify = () => {
423 if (! toast.isActive(this.toastId)) {
424 this.toastId = toast("I cannot be duplicated !");
425 }
426
427 toast("xxx-yyy cannot be duplicated", {
428 toastId: customToastId
429 });
430 }
431
432 render(){
433 return (
434 <div>
435 <button onClick={this.notify}>Notify</button>
436 </div>
437 );
438 }
439 }
440```
441
442### Delay notification appearance
443
444You can delay the notification appearance as shown below. Under the hood the lib simply use `setTimeout`.
445
446```js
447toast('Show now');
448toast('Show after 1sec', { delay: 1000 })
449```
450
451### Use a controlled progress bar
452
453Imagine you want to see the progress of a file upload. The example below feature axios, but it works with anything!
454
455```javascript
456 import React, { Component } from 'react';
457 import { toast } from 'react-toastify';
458 import axios from 'axios';
459
460 class Example extends Component {
461 upload = () => {
462 // we need to keep a reference of the toastId to be able to update it
463 let toastId = null;
464
465 axios.request({
466 method: "post",
467 url: "/foobar",
468 data: myData,
469 onUploadProgress: p => {
470 const progress = p.loaded / p.total;
471
472 // check if we already displayed a toast
473 if(toastId === null){
474 toastId = toast('Upload in Progress', {
475 progress: progress
476 });
477 } else {
478 toast.update(toastId, {
479 progress: progress
480 })
481 }
482 }
483 }).then (data => {
484 // Upload is done!
485 // The remaining progress bar will be filled up
486 // The toast will be closed when the transition end
487 toast.done(toast.id)
488 })
489 }
490
491 render(){
492 return (
493 <div>
494 <button onClick={this.upload}>Upload something</button>
495 </div>
496 );
497 }
498 }
499```
500
501### Update a toast
502
503When you update a toast, the toast options and the content are inherited but don't worry you can update them.
504
505![update-without-transition](https://user-images.githubusercontent.com/5574267/33761953-1ce2e0ea-dc0b-11e7-8967-a63c1185ce0e.gif)
506
507#### Basic example
508
509```js
510import React, { Component } from 'react';
511import { toast } from 'react-toastify';
512
513class Update extends Component {
514 toastId = null;
515
516 notify = () => this.toastId = toast("Hello", { autoClose: false });
517
518 update = () => toast.update(this.toastId, { type: toast.TYPE.INFO, autoClose: 5000 });
519
520 render(){
521 return (
522 <div>
523 <button onClick={this.notify}>Notify</button>
524 <button onClick={this.update}>Update</button>
525 </div>
526 )
527 }
528}
529```
530
531#### Update the content
532
533If you want to change the content it's straightforward as well. You can render any valid element including a react component. Pass your value to a `render` option as follow:
534
535```js
536 // With a string
537 toast.update(this.toastId, {
538 render: "New content",
539 type: toast.TYPE.INFO,
540 autoClose: 5000
541 });
542
543// Or with a component
544toast.update(this.toastId, {
545 render: <MyComponent />
546 type: toast.TYPE.INFO,
547 autoClose: 5000
548 });
549```
550
551#### Update the toast id
552
553If you want to update the `toastId` it can be done. But don't forget to use the new id!
554
555```js
556const myNewToastId = 'loremIpsum';
557
558toast.update(this.toastId, {
559 render: "New content",
560 type: toast.TYPE.INFO,
561 autoClose: 5000,
562 toastId: myNewToastId
563});
564
565toast.update(myNewToastId, {
566 render: <MyComponent />
567 autoClose: 6000
568});
569```
570
571#### Apply a transition
572
573By default, when you update a toast, there is no transition applied. If you want to apply a transition, it can be done via the `className` or the `transition` option:
574
575![update-with-transition](https://user-images.githubusercontent.com/5574267/33761952-1cc9d55a-dc0b-11e7-9a05-29186ea1c1f0.gif)
576
577```js
578// with css
579toast.update(this.toastId, {
580 render: "New Content",
581 type: toast.TYPE.INFO,
582 //Here the magic
583 className: 'rotateY animated'
584})
585
586// with glamor
587toast.update(this.toastId, {
588 render: "New Content",
589 type: toast.TYPE.INFO,
590 //Here the magic
591 className: css({
592 transform: "rotateY(360deg)",
593 transition: "transform 0.6s"
594 })
595})
596
597// with transition
598toast.update(this.toastId, {
599 render: "New Content",
600 type: toast.TYPE.INFO,
601 //Here the magic
602 transition: Rotate
603})
604
605```
606
607#### Reset option or inherit from ToastContainer
608
609If you want to inherit props from the `ToastContainer`, you can reset an option by passing null.
610It's particulary useful when you remove the `closeButton` from a toast and you want it back during the update:
611
612```js
613class Update extends Component {
614 toastId = null;
615
616 notify = () => this.toastId = toast("Hello", {
617 autoClose: false,
618 closeButton: false // Remove the closeButton
619 });
620
621 update = () => toast.update(this.toastId, {
622 type: toast.TYPE.INFO,
623 autoClose: 5000,
624 closeButton: null // The closeButton defined on ToastContainer will be used
625 });
626
627 render(){
628 return (
629 <div>
630 <button onClick={this.notify}>Notify</button>
631 <button onClick={this.update}>Update</button>
632 </div>
633 )
634 }
635}
636```
637
638### Define callback
639
640You can define two callbacks on `toast`. They are really useful when the toast are not used only to display messages.
641
642- onOpen is called inside componentDidMount
643- onClose is called inside componentWillUnmount
644
645```javascript
646 import React, { Component } from 'react';
647 import { toast } from 'react-toastify';
648
649 class Hook extends Component {
650 notify = () => toast(<MyComponent foo="bar" />, {
651 onOpen: ({ foo }) => window.alert('I counted to infinity once then..'),
652 onClose: ({ foo }) => window.alert('I counted to infinity twice')
653 });
654
655 render(){
656 return <button onClick={this.notify}>Notify</button>;
657 }
658 }
659```
660
661### Listen for change
662
663If you want to know when a toast is displayed or removed, `toast` expose a `onChange` method:
664
665```js
666toast.onChange( numberOfToastDisplayed => {
667 // Do whatever you want
668});
669```
670
671### Set a custom close button or simply remove it
672
673#### Override the default one
674
675You can pass a custom close button to the `ToastContainer` to replace the default one.
676
677⚠️ **When you use a custom close button, your button will receive a ```closeToast``` function.
678You need to call it in order to close the toast.** ⚠️
679
680```javascript
681 import React, { Component } from 'react';
682 import { toast, ToastContainer } from 'react-toastify';
683
684 const CloseButton = ({ YouCanPassAnyProps, closeToast }) => (
685 <i
686 className="material-icons"
687 onClick={closeToast}
688 >
689 delete
690 </i>
691 );
692
693 class CustomClose extends Component {
694 notify = () => {
695 toast("The close button change when Chuck Norris display a toast");
696 };
697
698 render(){
699 return (
700 <div>
701 <button onClick={this.notify}>Notify</button>;
702 <ToastContainer closeButton={<CloseButton YouCanPassAnyProps="foo" />} />
703 </div>
704 );
705 }
706 }
707```
708
709#### Define it per toast
710
711```javascript
712 import React, { Component } from 'react';
713 import { toast } from 'react-toastify';
714
715 // Let's use the closeButton we defined on the previous example
716 class CustomClose extends Component {
717 notify = () => {
718 toast("The close button change when Chuck Norris display a toast",{
719 closeButton: <CloseButton YouCanPassAnyProps="foo" />
720 });
721 };
722
723 render(){
724 return <button onClick={this.notify}>Notify</button>;
725 }
726 }
727```
728
729#### Remove it
730
731Sometimes you don't want to display a close button. It can be removed globally or per toast. Pass
732`false` to `closeButton` props:
733
734- remove it by default
735
736```js
737 <ToastContainer closeButton={false} />
738```
739
740- remove it per toast
741
742```js
743 toast("hello", {
744 closeButton: false
745 })
746```
747
748-- if you removed it globally, you can display the default Button per toast (or you can set your custom button)
749
750```js
751 toast("hello", {
752 closeButton: true // or <FontAwesomeCloseButton />
753 })
754```
755
756### Add an undo option to a toast like google drive
757
758See it in action:
759
760[![Edit l2qkywz7xl](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/l2qkywz7xl)
761
762```javascript
763const ToastUndo = ({ id, undo, closeToast }) => {
764 function handleClick(){
765 undo(id);
766 closeToast();
767 }
768
769 return (
770 <div>
771 <h3>
772 Row Deleted <button onClick={handleClick}>UNDO</button>
773 </h3>
774 </div>
775 );
776}
777
778class App extends Component {
779 state = {
780 collection: data,
781 // Buffer
782 toRemove: []
783 };
784
785 // Remove the row id from the buffer
786 undo = id => {
787 this.setState({
788 toRemove: this.state.toRemove.filter(v => v !== id)
789 });
790 }
791
792 // Remove definetly
793 cleanCollection = () => this.setState({
794 // Return element which are not included in toRemove
795 collection: this.state.collection.filter(v => !this.state.toRemove.includes(v.id)),
796 //Cleanup the buffer
797 toRemove: []
798 });
799
800 // Remove row from render process
801 // then display the toast with undo action available
802 removeRow = e => {
803 const id = e.target.dataset.rowId;
804 this.setState({
805 toRemove: [...this.state.toRemove, id]
806 });
807 toast(<ToastUndo undo={this.undo} id={id} />, {
808 // hook will be called whent the component unmount
809 onClose: this.cleanCollection
810 });
811 };
812
813 renderRows() {
814 const { collection, toRemove } = this.state;
815
816 // Render all the element wich are not present in toRemove
817 // Im using data-attribute to grab the row id
818 return collection.filter(v => !toRemove.includes(v.id)).map(v => (
819 <tr key={v.id}>
820 <td>{v.firstName}</td>
821 <td>{v.lastName}</td>
822 <td>{v.email}</td>
823 <td>
824 <button onClick={this.removeRow} data-row-id={v.id}>
825 Delete
826 </button>
827 </td>
828 </tr>
829 ));
830 }
831
832 render() {
833 // Dont close the toast on click
834 return (
835 <div style={styles}>
836 <table>
837 <tbody>
838 <tr>
839 <th>name</th>
840 <th>firstname</th>
841 <th>gender</th>
842 <th />
843 </tr>
844 {this.renderRows()}
845 </tbody>
846 </table>
847 <ToastContainer closeOnClick={false} />
848 </div>
849 );
850 }
851}
852```
853
854### Replace the default transition
855
856There is 4 built-in transitions provided:
857
858<details>
859 <summary>Bounce</summary>
860 <img src ="https://user-images.githubusercontent.com/5574267/38770379-985f49c8-4012-11e8-9db1-5d4d1f26a3d5.gif" />
861</details>
862
863<details>
864 <summary>Slide</summary>
865 <img src ="https://user-images.githubusercontent.com/5574267/38770381-98a81d24-4012-11e8-8011-1190f3fb17c3.gif" />
866</details>
867
868<details>
869 <summary>Zoom</summary>
870 <img src ="https://user-images.githubusercontent.com/5574267/38770382-98c16342-4012-11e8-9abf-3cf3d3eabd8c.gif" />
871</details>
872<details>
873 <summary>Flip</summary>
874 <img src ="https://user-images.githubusercontent.com/5574267/38770380-9877dde4-4012-11e8-9485-0dc43346ce30.gif" />
875</details>
876
877Bounce is used by default but you can replace it by your own transition or by one of the list above:
878
879
880```js
881import { Slide, Zoom, Flip, Bounce } from 'react-toastify';
882
883 <ToastContainer
884 transition={Slide}
885 />
886//...
887 <ToastContainer
888 transition={YourCustomTransition}
889 />
890
891```
892You get the idea...
893
894### Define a custom enter and exit transition
895
896The toast relies on `react-transition-group` for the enter and exit transition. Any transition built with react-transition-group should work !
897
898![toastify_custom_trans](https://user-images.githubusercontent.com/5574267/31049179-0d52e14c-a62e-11e7-9abd-b0d169a0fadc.gif)
899
900
901I'll use the zoom animation from animate.css. Of course, you could create your own animation.
902
903```css
904/* style.css*/
905@keyframes zoomIn {
906 from {
907 opacity: 0;
908 transform: scale3d(.3, .3, .3);
909 }
910
911 50% {
912 opacity: 1;
913 }
914}
915
916.zoomIn {
917 animation-name: zoomIn;
918}
919
920@keyframes zoomOut {
921 from {
922 opacity: 1;
923 }
924
925 50% {
926 opacity: 0;
927 transform: scale3d(.3, .3, .3);
928 }
929
930 to {
931 opacity: 0;
932 }
933}
934
935.zoomOut {
936 animation-name: zoomOut;
937}
938
939/* Not needed with the cssTransition helper */
940
941.animate {
942 animation-duration: 800ms;
943}
944```
945
946#### Ease your life with the cssTransition helper
947
948The easiest way to roll your own transition is by using the `cssTransition` helper. Doing so you don't need to deal with `react-transition-group`. You only need to provide the `enter` and the `exit` class name, the transition `duration` is set
949to `750ms` by default but it can be overridden:
950
951```js
952import React, { Component } from 'react';
953import { toast, cssTransition } from 'react-toastify';
954import './style.css';
955
956const Zoom = cssTransition({
957 enter: 'zoomIn',
958 exit: 'zoomOut',
959 // default to 750ms, can be omitted
960 duration = 750,
961});
962
963class App extends Component {
964 notify = () => {
965 toast("ZoomIn and ZoomOut", {
966 transition: Zoom,
967 autoClose: 5000
968 });
969 };
970
971 render(){
972 return <button onClick={this.notify}>Notify</button>;
973 }
974}
975```
976
977##### Different duration for enter and exit
978
979If you want the transition duration to be different between the enter and exit transition pass an array:
980
981```js
982import React, { Component } from 'react';
983import { toast, cssTransition } from 'react-toastify';
984import './style.css';
985
986const Zoom = cssTransition({
987 enter: 'zoomIn',
988 exit: 'zoomOut',
989 duration: [500, 800]
990});
991
992class App extends Component {
993 notify = () => {
994 toast("ZoomIn and ZoomOut", {
995 transition: Zoom,
996 autoClose: 5000
997 });
998 };
999
1000 render(){
1001 return <button onClick={this.notify}>Notify</button>;
1002 }
1003}
1004```
1005
1006##### Handle transition based on the toast position
1007
1008Some transitions are based on the toast position. This is the case for the default one. If you pass `appendPosition` to the `cssTransition` helper as shown below, the current position will be appended to the `enter` and `exit` class name:
1009
1010```js
1011import React, { Component } from 'react';
1012import { toast, cssTransition } from 'react-toastify';
1013import './style.css';
1014
1015const Zoom = cssTransition({
1016 // zoomIn will become zoomIn--top-right or zoomIn--top-left and so on
1017 enter: 'zoomIn',
1018 // zoomIn will become zoomOut--top-right or zoomOut--top-left and so on
1019 exit: 'zoomOut',
1020 // default to false
1021 appendPosition: true
1022});
1023
1024class App extends Component {
1025 notify = () => {
1026 toast("ZoomIn and ZoomOut", {
1027 transition: Zoom,
1028 autoClose: 5000
1029 });
1030 };
1031
1032 render(){
1033 return <button onClick={this.notify}>Notify</button>;
1034 }
1035}
1036```
1037
1038#### Create a transition from scratch
1039
1040```js
1041import React, { Component } from 'react';
1042import { toast } from 'react-toastify';
1043import Transition from 'react-transition-group/Transition';
1044import './style.css';
1045
1046const ZoomInAndOut = ({ children, position, ...props }) => (
1047 <Transition
1048 {...props}
1049 {/* Same as the animation duration */}
1050 timeout={800}
1051 onEnter={ node => node.classList.add('zoomIn', 'animate')}
1052 onExit={node => {
1053 node.classList.remove('zoomIn', 'animate');
1054 node.classList.add('zoomOut', 'animate');
1055 }}
1056 >
1057 {children}
1058 </Transition>
1059);
1060
1061class App extends Component {
1062 notify = () => {
1063 toast("ZoomIn and ZoomOut", {
1064 transition: ZoomInAndOut,
1065 autoClose: 5000
1066 });
1067 };
1068
1069 render(){
1070 return <button onClick={this.notify}>Notify</button>;
1071 }
1072}
1073
1074```
1075
1076### Swipe to remove
1077
1078You can swipe the toast to remove it:
1079
1080![drag](https://user-images.githubusercontent.com/5574267/38770523-9438ff7c-4014-11e8-93a5-acd7dbdae52b.gif)
1081
1082#### Define the width percentage to remove the toast
1083
1084You need to drag 80% of the toast width to remove it. This can be changed to fit your need:
1085
1086- Replace the default one:
1087
1088```js
1089<ToastContainer draggablePercent={60}>
1090```
1091
1092- Replace per toast:
1093
1094```js
1095toast('Hello', {
1096 draggablePercent: 60
1097});
1098```
1099
1100#### Disable it
1101
1102- Disable by default for all toast:
1103
1104```js
1105<ToastContainer draggable={false}>
1106```
1107
1108- Disable per toast:
1109
1110```js
1111toast('Hello', {
1112 draggable: false
1113});
1114```
1115
1116
1117### Le style
1118
1119#### style with css classes
1120
1121```javascript
1122toast("Custom style",{
1123 className: 'black-background',
1124 bodyClassName: "grow-font-size",
1125 progressClassName: 'fancy-progress-bar'
1126});
1127```
1128
1129#### style with glamor
1130
1131```javascript
1132import { css } from 'glamor';
1133
1134toast("Custom style",{
1135 className: css({
1136 background: 'black'
1137 }),
1138 bodyClassName: css({
1139 fontSize: '60px'
1140 }),
1141 progressClassName: css({
1142 background: "repeating-radial-gradient(circle at center, red 0, blue, green 30px)"
1143 })
1144});
1145```
1146
1147#### Define style globally
1148
1149```js
1150<ToastContainer
1151 className='toast-container'
1152 toastClassName="dark-toast"
1153 progressClassName={css({
1154 height: "2px"
1155 })}
1156/>
1157```
1158
1159#### Right to left support
1160
1161Your app need to support rtl content? Set the rtl props to `true`:
1162
1163```javascript
1164 render(){
1165 return(
1166 {/*Component*/}
1167 <ToastContainer rtl />
1168 {/*Component*/}
1169 );
1170 }
1171```
1172
1173#### Include the bare minimum style
1174
1175To include the bare minimum required style you can do as follow:
1176
1177```js
1178import 'react-toastify/dist/ReactToastify.minimal.css`;
1179```
1180
1181### Mobile
1182
1183On mobile the toast will take all the available width.
1184
1185![react toastiy mobile](https://user-images.githubusercontent.com/5574267/28754040-ae7195ea-753d-11e7-86e1-f23c5e6bc531.gif)
1186
1187## Api
1188
1189### ToastContainer
1190
1191| Props | Type | Default | Description |
1192|----------------------|------------------------|-----------|-----------------------------------------------------------------------------------------------------|
1193| position | string | top-right | One of top-right, top-center, top-left, bottom-right, bottom-center, bottom-left |
1194| autoClose | false or number | 5000 | Delay in ms to close the toast. If set to false, the notification need to be closed manualy |
1195| closeButton | React Element or false | - | A React Component to replace the default close button or `false` to hide the button |
1196| transition | function | - | A reference to a valid react-transition-group/Transition component |
1197| hideProgressBar | bool | false | Display or not the progress bar below the toast(remaining time) |
1198| pauseOnHover | bool | true | Keep the timer running or not on hover |
1199| pauseOnFocusLoss | bool | true | Pause the timer when the window loses focus |
1200| rtl | bool | false | Support right to left content |
1201| closeOnClick | bool | true | Dismiss toast on click |
1202| newestOnTop | bool | false | Display newest toast on top |
1203| className | string\|object | - | Add optional classes to the container |
1204| style | object | - | Add optional inline style to the container |
1205| toastClassName | string\|object | - | Add optional classes to the toast |
1206| bodyClassName | string\|object | - | Add optional classes to the toast body |
1207| progressClassName | string\|object | - | Add optional classes to the progress bar |
1208| progressStyle | object | - | Add optional inline style to the progress bar |
1209| draggable | bool | true | Allow toast to be draggable |
1210| draggablePercent | number | 80 | The percentage of the toast's width it takes for a drag to dismiss a toast(value between 0 and 100) |
1211| enableMultiContainer | bool | - | Enable multi toast container support |
1212| containerId | string\number | - | Container id used to match toast with the same containerId |
1213| role | string | alert | Defne the ARIA role for the toasts |
1214
1215
1216
1217### toast
1218
1219All the method of toast return a **toastId** except `dismiss` and `isActive`.
1220The **toastId** can be used to remove a toast programmatically or to check if the toast is displayed.
1221
1222
1223| Parameter | Type | Required | Description |
1224| --------- | ------- | ------------- | ------------------------------------------------------------- |
1225| content | string or React Element | ✓ | Element that will be displayed |
1226| options | object | ✘ | Options listed below | |
1227
1228- Available options :
1229 - `type`: Kind of notification. One of "default", "success", "info", "warning", "error". You can use `toast.TYPE.SUCCESS` and so on to avoid any typo.
1230 - `onOpen`: Called inside componentDidMount
1231 - `onClose`: Called inside componentWillUnmount
1232 - `autoClose`: same as ToastContainer.
1233 - `closeButton`: `false` to disable, a `React Component` to replace or `true` to display the default button.
1234 - `transition`: same as ToastContainer.
1235 - `closeOnClick`: same as ToastContainer.
1236 - `hideProgressBar`: same as ToastContainer.
1237 - `position`: same as ToastContainer
1238 - `pauseOnHover`: same as ToastContainer
1239 - `pauseOnFocusLoss`: same as ToastContainer
1240 - `className`: same as ToastContainer toastClassName
1241 - `bodyClassName`: same as ToastContainer
1242 - `progressClassName`: same as ToastContainer
1243 - `draggable`: same as ToastContainer
1244 - `draggablePercent`: same as ToastContainer
1245 - `role`: same as ToastContainer
1246 - `toastId`: optional integer or string to manually set a toastId. If an invalid type is provided a generated toastId will be used
1247 - `progress`: a value between 0..1 to control the progress bar
1248 - `render`: string or React Element, only available when calling update
1249 - `delay`: a number to let you delay the toast appearance
1250 - `containerId`: string or number to match a specific Toast container
1251 - `onClick`: Called when click inside Toast notification
1252
1253:warning:️ *Toast options supersede ToastContainer props* :warning:
1254
1255:warning:️ *Manually setting a toastId overwrite automatically generated toastIds* :warning:
1256
1257```js
1258const Img = ({ src }) => <div><img width={48} src={src} /></div>;
1259const options = {
1260 onOpen: props => console.log(props.foo),
1261 onClose: props => console.log(props.foo),
1262 autoClose: 6000,
1263 closeButton: <FontAwesomeCloseButton />,
1264 type: toast.TYPE.INFO,
1265 hideProgressBar: false,
1266 position: toast.POSITION.TOP_LEFT,
1267 pauseOnHover: true,
1268 transition: MyCustomTransition,
1269 progress: 0.2
1270 // and so on ...
1271};
1272
1273const toastId = toast(<Img foo={bar}/>, options) // default, type: 'default'
1274toast(({ closeToast }) => <div>Render props like</div>, options);
1275toast.success("Hello", options) // add type: 'success' to options
1276toast.info("World", options) // add type: 'info' to options
1277toast.warn(<Img />, options) // add type: 'warning' to options
1278toast.error(<Img />, options) // add type: 'error' to options
1279toast.dismiss() // Remove all toasts !
1280toast.dismiss(toastId) // Remove given toast
1281toast.isActive(toastId) //Check if a toast is displayed or not
1282toast.update(toastId, {
1283 type: toast.TYPE.INFO,
1284 render: <Img foo={bar}/>
1285});
1286toast.done(toastId) // completes the controlled progress bar
1287toast.configure({
1288 autoClose: 8000,
1289 draggable: false,
1290 //same as ToastContainer props
1291})
1292toast.useLazyContainer(false) // disable lazy container
1293```
1294
1295### cssTransition
1296
1297| Parameter | Type | Required | Default | Description |
1298|----------------|--------|----------|---------|------------------------------------------------------------------------------------------------------------|
1299| enter | string | ✓ | - | The class name that will be used when the toast enter |
1300| exit | string | ✓ | - | The class name that will be used when the toast exit |
1301| duration | number\| Array<number> | ✘ | 750 | The transition duration in ms. |
1302| appendPosition | bool | ✘ | false | Append or not the position to the class name: `yourClassName--top-right`, `yourClassName--bottom-left`... |
1303
1304```js
1305import { cssTransition } from 'react-toastify';
1306
1307const Zoom = cssTransition({
1308 enter: 'zoomIn',
1309 exit: 'zoomOut',
1310 duration: 750,
1311 appendPosition: false
1312});
1313
1314const Zoom = cssTransition({
1315 enter: 'zoomIn',
1316 exit: 'zoomOut',
1317 duration: [500, 600],
1318 appendPosition: false
1319});
1320```
1321
1322## Browser Support
1323
1324![IE](https://cloud.githubusercontent.com/assets/398893/3528325/20373e76-078e-11e4-8e3a-1cb86cf506f0.png) | ![Chrome](https://cloud.githubusercontent.com/assets/398893/3528328/23bc7bc4-078e-11e4-8752-ba2809bf5cce.png) | ![Firefox](https://cloud.githubusercontent.com/assets/398893/3528329/26283ab0-078e-11e4-84d4-db2cf1009953.png) | ![Opera](https://cloud.githubusercontent.com/assets/398893/3528330/27ec9fa8-078e-11e4-95cb-709fd11dac16.png) | ![Safari](https://cloud.githubusercontent.com/assets/398893/3528331/29df8618-078e-11e4-8e3e-ed8ac738693f.png) | ![Edge](https://raw.githubusercontent.com/alrra/browser-logos/master/src/edge/edge_48x48.png)
1325--- | --- | --- | --- | --- | --- |
1326IE 11+ ✔ | Latest ✔ | Latest ✔ | Latest ✔ | Latest ✔ | Latest ✔ |
1327
1328## Release Notes
1329
1330You can find the release note for the latest release [here](https://github.com/fkhadra/react-toastify/releases/latest)
1331
1332
1333You can browse them all [here](https://github.com/fkhadra/react-toastify/releases)
1334
1335## Contribute
1336
1337Show your ❤️ and support by giving a ⭐. Any suggestions are welcome ! Take a look at the contributing guide.
1338
1339You can also find me on [reactiflux](https://www.reactiflux.com/). My pseudo is Fadi.
1340
1341## License
1342
1343Licensed under MIT