react-toastify

React notification made easy πŸš€ !

MIT License

Downloads
8.9M
Stars
12.2K
Committers
89

Bot releases are visible (Hide)

react-toastify - v10.0.0 Latest Release

Published by fkhadra 9 months ago

What is new in v10

The code for this release has been sitting on my computer for almost a year but with so many things going on it was hard for me to release it but it's finally there! A good chunk of the code has been rewritten, a bunch of bugs have been fixed. I've also addressed the oldest open feature request (Jan 10, 2020) πŸ˜†.

stacked

Features

Play or pause the timer programmatically

By default, when the notification is hovered or the window loses focus, the timer for dismissing the notification is paused. There are many other situations where you might want to pause the timer as well. For instance, consider wanting to toggle the notification timer based on the document's visibility. This wasn't possible to do previously, but with the new API, it's a breeze.

document.addEventListener("visibilitychange", () => {
  if (document.visibilityState === "visible") {
    toast.play({ id: "123" });
  } else {
    toast.pause({ id: "123" });
  }
});

More usages:

  • Play/pause all toasts
toast.play()
toast.pause()
  • Play/pause all toasts for a given container
toast.play({ containerId: "123" })
toast.pause({ containerId: "123" })
  • Play/pause toast that has a given id regardless the container
toast.play({ id: "123" })
toast.pause({ id: "123" })
  • Play/pause toast that has a given id for a specific container
toast.play({ id: "123", containerId: "12" })
toast.pause({ id: "123", containerId: "12" })

Remove notification from a given container

This feature was the oldest one in the backlog (Jan 10, 2020). I don't know if the user who requested this feature is still using the library but I bet thanks to her/him, a bunch of user will be happy.

  • Remove all toasts that belongs to a given container
toast.dismiss({ container: "123" })
  • Remove toast that has a given id for a specific container
toast.dismiss({ id: "123", containerId: "12" })

The method is backward compatible. toast.dismis() and toast.dismiss("123") work as usual.

Check if a notification is active for a given container

You can limit the call to toast.isActive to a specific container.

  toast.isActive(toastId, containerId)

Better typescript inference when using data

When providing data to the notification, the content of data is correctly infered by typescript.

toast((props) => {
  return <div>{props.data.foo}</div>
},{
  data: {
    foo: "bar"
  }
})

IconProps now receives isLoading

When providing your own logic to display the icon, you now have access to the isLoading field.

const CustomIcon = props => {
  if (props.isLoading) return <Spinner />;

  switch (props.type) {
    case 'info':
      return <Info color={iconColor} />;
    case 'success':
      return <Success color={iconColor} />;
    case 'error':
      return <Error color={iconColor} />;
    case 'warning':
      return <Warning color={iconColor} />;
    default:
      return undefined;
  }
};


<ToastContainer icon={CustomIcon} />

Stacked Notifications

The initial release for this feature was planned right after the release of the v9. The code was their but things happen in life and I wasn't able to focus on the project that much.

That being said, I'm glad to finally release it.

stacked

To enable it, add the stacked prop to the ToastContainer. I also suggest to disable the progress bar :).

<ToastContainer stacked />

Progress bar background trail

The progress bar leaves a background trail by default.

The opacity of the trail can be customized by overriding the css variable --toastify-color-progress-bgo.

  // disable the trail
  --toastify-color-progress-bgo: 0;

  // increase the opacity
  --toastify-color-progress-bgo: .8;

Breaking Changes

React 18 is the minimum required version, but...

The minimun version of react required is now 18. This version has been released for more than a year. Nextjs, react-query already did this move as well, so I believe it's a good time for the library as well.

That being said, I know that not all code base have the chance to be running on the latest version of react, so I'm considering to have a package for v17 if the demand is high enough.

The enableMultiContainer prop has been removed

The enableMultiContainer props is not needed anymore and has been removed. As long as your container has an id assigned then you are good to go.

// before
<ToastContainer id="myContainer" enableMultiContainer />

// now πŸŽ‰
<ToastContainer id="myContainer"  />

The toast.position and toast.type constants have been removed

The toast.POSITION and toast.TYPE constants have been removed. Typescript came a long way since the initial release of the library. The ecosystem has matured to a point where such constants are not needed anymore.

Change for some defaults

The closeOnClick prop is now false by default instead of true. When using the library I keep on turning this feature off which make me realize that it was not a good default in the first place. To turn it on do as follow

<ToastContainer closeOnClick />

The draggable prop is set to touch by default instead of true. Which means that, by default, notifications are only draggable on touch devices (most likely mobiles and tablets). While swipping a notification on mobile feels natural, dragging on desktop is not. If you want your notification to be draggable regardless of the device type just set draggable to true.

<ToastContainer draggable />

Bug Fixes and Chore

  • Remove defaultProps on ToastContainer as it's deprecated #970
  • Fix className from ToastOptions overrides the toastClassName in ToastContainer props instead of appending #956
  • Rewrite tests using component testing #923
  • Memory leak while using multiple containers are goes on in v9.1.1 #910
  • React toast is showing multiple time. #744
  • onClose event trigger 2 times. #741
react-toastify - v9.1.3

Published by fkhadra over 1 year ago

Release note

  • Add support for RSC (next app router): #951
  • Partially address Toast is undefined || Uncaught TypeError: Cannot read properties of undefined (reading 'content') #858 #952
  • Bump dependencies
react-toastify - v9.1.2

Published by fkhadra over 1 year ago

Release notes

Mainly bug fixes as I'm working on the next major release.

πŸ•·Bugfixes

  • fix resetting options #921 #920
  • fix autoClose on update #918
  • fix invalid CSS translate #925
react-toastify - v9.1.0

Published by fkhadra almost 2 years ago

Release notes

πŸš€ Features

  • toast.promise let you type data for each state. This is useful when rendering something based on the response.

For example:

interface Success {
  username: string
}

interface Error {
  err: string
}

toast.promise<Success,Error>(myPromise, {
  success: {
    render({ data }) {
      return data.username;
    }
  },
  error: {
    render({ data }) {
      return data.err;
    }
  }
})

  • toast.update accepts a generic as well to specify the data type
interface TData {
  username: string
}

toast.update<TData>(id, {
  data: payload,
  render({ data }) {
    return `hello ${data.username}`
  }
})

πŸ•· Bugfixes

  • fix progress countdown stops on mobile #580
  • prevent clash with ios native gesture #397
  • fix toast when a word is too long #864
  • fix missing types declarations in exports #843
  • fix toast.done not dismissing toast #853
  • fix cursor when close on click is false #839

🚨 Deprecated API

Added deprecation notice for the API below. They will be removed in the next major release

API Why Alternative
onClick Not used that much, it's increasing the API surface for nothing Can easily be implemented in userland. Just render a react component and attach the handler to it. toast(<div onClick={doSomething}>hello</div>)
onOpen Does not play well with useEffect behavior in react18 (runs twice in dev mode) see #741 A better approach is to use toast.onChange see https://fkhadra.github.io/react-toastify/listen-for-changes/
onClose Does not play well with useEffect behavior in react18 (runs twice in dev mode) see #741 A better approach is to use toast.onChange see https://fkhadra.github.io/react-toastify/listen-for-changes/
toast.POSITION Reduce bundle size :) Thanks to typescript, we now have autocomplete
toast.TYPE Reduce bundle size :) Thanks to typescript, we now have autocomplete

βš™οΈ Chore

  • bump dependencies
  • refactor internal
react-toastify - v9.0.8

Published by fkhadra about 2 years ago

Release notes

🐞Bugfixes

  • fix draggable in strict mode #752
  • fix sass import #771
  • fix progress bar overflow for WebKit browser(safari, ios...) #791
  • fix dismissed toasts while the container is unmounted still appear when the container is mounted #811
  • fix AutoClose doesn't work on update #810 #782 #720

Chore

  • master branch renamed to main πŸ’–
react-toastify - v9.0.7

Published by fkhadra over 2 years ago

Release note

Bugfix

  • fix memory leak when multiple containers are used #772, thanks to @roblotter

Chore

  • build artifacts are no longer minified. This was causing issues with some bundlers like vitejs #797
react-toastify - v9.0.6

Published by fkhadra over 2 years ago

Release note

Bugfix

  • fix missing generic in useNotificationCenter typing #796
react-toastify - v9.0.5

Published by fkhadra over 2 years ago

Release note

πŸ•· Bugfix

  • inject-style has now the correct file-name in bundle #779
react-toastify - v9.0.4

Published by fkhadra over 2 years ago

Release note

This release does not work with CRA v4(2 years old) due to the lack of support for es modules. I strongly advise to upgrade to lastest CRA if possible.
Alternative solution:

Bugfix

  • use mjs extensions for es modules #767 thank to @mikebarkmin
react-toastify - v9.0.3

Published by fkhadra over 2 years ago

Release notes

πŸ•· Bugfix

  • Fix icon not updating after calling toast.update #770
react-toastify - v9.0.2

Published by fkhadra over 2 years ago

Release notes

Thanks to @Rambatino, @grit96, @Vl3oss, @eolme for this release

πŸ•· Bug fixes

  • typo #764
  • pass toast styles through #763
  • add function type in icon prop #761
  • closeButton/icon types/rendering #758
  • fix empty data object in NotificationCenter #757
react-toastify - v9.0.0

Published by fkhadra over 2 years ago

Release note

πŸš€ What is new in v9

Say hello to addons! What are addons? So, addons are like DLCs in video games but for react-toastify πŸ˜†. More seriously, you can think of it as utilities built around react-toastify. For example, custom theme, hooks, components etc...

useNotificationCenter

The first addon that I would like to introduce is the useNotificationCenter headless hook! As the name suggests, it let you build your notification center on top of react-toastify. See for yourself πŸ‘‡

https://user-images.githubusercontent.com/5574267/166549174-48422a61-ff7b-4eeb-b53f-d903db3d1595.mov

Another example using MUI.

Edit mui-notification-center
Check the documentation for more details.

Stacked toasts

This second addon will be released later. There are a bunch of details that I need to cover and I don't want to release something too buggy. Nevertheless, I'm really excited about it and I think it's worth showcasing anyway.

I call it StackedContainer for now, it's an alternative to the ToastContainer component.

stacked-container

πŸ’₯ Breaking changes

There are 2 breaking changes. The API change for toast.onChange and the removal of toast.configure.

toast.onChange

The previous API was returning the numberOfToastDisplayed and the containerId. Honestly, this API seems to be incomplete.

For example, with the old API, if I wanted to do some logging this would be very difficult because I don't have enough data to log.

toast.onChange((numberOfToastDisplayed, containerId) => {
  logger.info("nothing useful to log, ...")
})

The new API offers more possibilities. The callback will receive a ToastItem. The item provides a bunch of useful properties status, content, id, data, etc...

interface ToastItem<Data = {}> {
    id: Id;
    content: React.ReactNode;
    theme?: Theme;
    type?: TypeOptions;
    isLoading?: boolean;
    containerId?: Id;
    data: Data;
    icon?: React.ReactNode | false;
    status: "added" | "removed" | "updated" 
}

const unsubscribe = toast.onChange((payload: ToastItem) => {
  switch (payload.status) {
    case "added":
      // new toast added
      break;
    case "updated":
      // toast updated
      break;
    case "removed":
      // toast has been removed
      break;
  }
});

For example, if I want to log something every time there is a new error notification, with the new API it's trivial

toast.onChange(payload => {
  if(payload.status === "added" && payload.type === toast.TYPE.ERROR) {
    logger.error({
      createdAt: Date.now(),
      content: payload.content,
      data: payload.data
    })
  }
})

toast.configure removal

toast.configure works fine for most cases but the current implementation has one main issue. It does not work with react context because it creates a new react tree.
That being said, having 2 APIs to do the same thing is a bad thing.

πŸ•· Bug fixes

  • #725 the success toast on promise does not disappear when resolving too quickly
  • #711 updated toast sometimes has wrong styles
  • #700 generics are not used for toast.promise's result type if you use a custom render method
react-toastify - v8.2.0

Published by fkhadra over 2 years ago

Release note

  • add deprecation notice for toast.configure.
  • add deprecation notice for toast.onChange. API for this method will change in the next major release

πŸ•· Bugfixes

  • fix #707 Promise toast does not close automatically if promise resolves too quickly

βš™οΈ Chore

  • bump parcel to latest version
react-toastify - v8.1.1

Published by fkhadra over 2 years ago

Release notes

πŸ•· Bug fixes

  • fix #702 autoClose duration start after the entrance animation finish
  • fix #689 prevents promise without success to hang on to the pending state
  • fix #645 and #618 onClose now work as expected!
  • fix #694 Fix error in Chrome: remove preventDefault from passive listener

βš™οΈ Chore

  • #703 the ToastPromiseParams is now exported
  • exit animation on safari are not conflicting with drag transition anymore

Thanks to @03c, @wilson-webdev, @essential-randomness for their contributions

react-toastify - v8.1.0

Published by fkhadra almost 3 years ago

Release notes

πŸš€ Features

  • add support for optional stages in promise #646
react-toastify - v8.0.3

Published by fkhadra about 3 years ago

Release notes

🐞 Bugfixes

  • fix text-align has not effect on content #657
  • fix disabling icon individually #658
  • fix tree shaking #641
react-toastify - v8.0.2

Published by fkhadra about 3 years ago

Release Notes

Bugfix

  • fix #635 Icon on safari not displayed
react-toastify - v8.0.1

Published by fkhadra about 3 years ago

Release notes

Features

  • toast.promise accept function that returns a promise.
react-toastify - v8.0.0

Published by fkhadra about 3 years ago

React-toastify has been around for 5 years(will turn five the 8 November πŸŽ‚). Since the beginning, one of the goals was to provide a library that is highly customizable and also able to work out of the box. Every major release introduces breaking changes but this is for the best πŸ‘Œ.

React toastify

πŸš€ Features

New look

Notifications of different types (toast.info, toast.error, toast.success, toast.warning) display an icon associated with the selected type. You can also notice that the progress bar color matches the type color.

Don't be afraid 😱, if you don't like those icons you can use your own or remove them. This is what it looks like in practice.

toast("Default toast behavior is untouched, no icon to display");
toast.info("Lorem ipsum dolor"); // same as toast(message, {type: "info"});
toast.error("Lorem ipsum dolor")
toast.success("Lorem ipsum dolor")
toast.warn("Lorem ipsum dolor")
toast.error("Without icon", {
  icon: false
});
toast.success("You can provide any string", {
  icon: "πŸš€"
});
// custom icons have access to the theme and the toast type
toast.success("And of course a component of your choice", {
  icon: MyIcon
});
toast.success("Even a function, given you return something that can be rendered", {
  icon: ({theme, type}) =>  <img src="url"/>
});
//Disable icons
<ToastContainer icon={false} />

Clear separation between type and theme

Prior to v8, toast.info, toast.error, etc... Would display respectively a blue notification, a red notification, etc... This is not the case anymore. There are 3 distinct themes: light, dark, colored. The theme can be applied globally or per notification.

//Set the theme globally 
<ToastContainer theme="dark" />

// define per toast
toast.info("Display a dark notification of type info");
toast.info("Display a light notification of type info", { theme: "light" });
toast.info("Display a blue notification of type info", { theme: "colored" });

This separation will benefit theming in the future.

I promise this is new, I'll tell you if you await

The library exposes a toast.promise function. Supply a promise and the notification will be updated if it resolves or fails. When the promise is pending a spinner is displayed. Again you hide it, I bet you already know how toπŸ˜†.

Let's start with a simple example

const resolveAfter3Sec = new Promise(resolve => setTimeout(resolve, 3000));
toast.promise(
    resolveAfter3Sec,
    {
      pending: 'Promise is pending',
      success: 'Promise resolved πŸ‘Œ',
      error: 'Promise rejected 🀯'
    }
)

Displaying a simple message is what you would want to do in 90% of cases. But what if the message you want to display depends on the promise response, what if you want to change some options for the error notification? Rest assured, under the hood, the library uses toast.update. Thanks to this, you have full control over each notification.

const resolveWithSomeData = new Promise(resolve => setTimeout(() => resolve("world"), 3000));
toast.promise(
    resolveAfter3Sec,
    {
      pending: 'Promise is pending',
      success: {
        render({data}){
          return `Hello ${data}`
        },
        // other options
        icon: "🟒",
      },
      error: {
        render({data}){
          // When the promise reject, data will contains the error
          return <MyErrorComponent message={data.message} />
        }
      }
    }
)

If you want to take care of each step yourself you can use toast.loading and update the notification yourself.

const id = toast.loading("Please wait...")
//do something else
toast.update(id, { render: "All is good", type: "success" });

Pass data even when you are not rendering a react component

One way to pass data to the notification was to use the context api or provide your own component. Starting v8 a data option is now available to make it easier.

toast(({data}) => `Hello ${data}`, {
  data: "world"
})

I just want to change few colors

Most of the time, users are ok with the default style, they just want to change some colors to match their brand. I think one way to improve the DX for all of us is to embrace CSS variables. That's why the library has switched to css variables!
All you want is to change the color of the progress bar? No problem

:root{
  // this is the default value below
  --toastify-color-progress-light: linear-gradient(
    to right,
    #4cd964,
    #5ac8fa,
    #007aff,
    #34aadc,
    #5856d6,
    #ff2d55
  );
}

You can find the list of all exposed variables here

πŸ’₯ Breaking changes

There are few breaking changes.

  • The separation between theme and type. The type dark has been removed
// before v8
toast("hello", {
  type: "dark"
})
// toast.TYPE.DARK is no longer available

// in v8
toast("hello", {
  theme: "dark"
})
// or
toast.dark("hello")
  • Notifications of different types are not colored by default, but they look pretty by default now πŸ˜†. You can use the colored theme to get the same behavior as the previous version
toast.info("hello", {
  theme: "colored"
})
// or apply the theme globally
<ToastContainer theme="colored" />
  • An icon is displayed by default for the notificaiton of type info, error, warning, success
// to opt-out gloablly from this behavior
<ToastContainer icon={false} />

// or per toast
toast.info("hello", {
  icon: false
});
  • the following css classes has been removed
.Toastify__toast--dark {
}
.Toastify__toast--default {
}
.Toastify__toast--info {
}
.Toastify__toast--success {
}
.Toastify__toast--warning {
}
.Toastify__toast--error {
}

βš™οΈ Chore

  • update all dependencies

That's it for this release. Thank you for using react-toastify and happy coding!

react-toastify - v7.0.4

Published by fkhadra over 3 years ago

Release notes

πŸ› Bugfix

  • fix #572 flex layout issue(regression)
  • fix #577 border-radius in mobile is not 0. Thanks to @mateuszpigula
  • fix #481 clearWaitingQueue not working
  • fix #589 accessibility issues with progressbar

Chore

  • bump dependencies