Skip to content
Search

React-hot-toast

lastmod 2024-01-31created 2024-01-314 edits

The Best React Notifications in Town

Simple usage

Install package: It weighs less than 5kb

yarn add react-hot-toast

Add Toaster to your app. Make sure it's placed at the top

<div><Toaster/></div>

Tip

For NextJS, it can be placed in the Top-Level Server Side Component Layout. In my case, at the end of the Top Level

<body>

, I added it the way you would add a

<Script>

.

Start toasting! Call it from anywhere

toast("Hello World")

Tailwind Custom example

Following the example on the official website, the pop-up animation doesn't appear. So you need to add a tailwind theme extension to the tailwind.config.js file as below:

/** @type {import('tailwindcss').Config} */
module.exports = {
  ...
  theme: {
    extend: {
      animation: {
        enter: 'enter 200ms ease-out',
        'slide-in': 'slide-in 1.2s cubic-bezier(.41,.73,.51,1.02)',
        leave: 'leave 150ms ease-in forwards',
      },
      keyframes: {
        enter: {
          '0%': {transform: 'scale(0.9)', opacity: 0},
          '100%': {transform: 'scale(1)', opacity: 1},
        },
        leave: {
          '0%': {transform: 'scale(1)', opacity: 1},
          '100%': {transform: 'scale(0.9)', opacity: 0},
        },
        'slide-in': {
          '0%': {transform: 'translateY(-100%)'},
          '100%': {transform: 'translateY(0)'},
        },
      },
    },
  },
  ...
};

Button Component TypeScript:

'use client';

import type {HTMLAttributes, PropsWithChildren} from 'react';
import toast from 'react-hot-toast';
import {CheckmarkIcon, ErrorIcon} from 'react-hot-toast';

interface CopyUrlButtonProps
  extends PropsWithChildren<HTMLAttributes<HTMLButtonElement>> {
  successLabel?: string;
  errorLabel?: string;
}

export default function CopyUrlButton(props: CopyUrlButtonProps) {
  const {successLabel, errorLabel, children, ...attrs} = props;
  const handlerClick = async () => {
    try {
      await navigator.clipboard.writeText(window.location.href);
      if (successLabel) {
        toast.custom(t => {
          return (
            <div
              className={`${
                t.visible ? 'animate-enter' : 'animate-leave'
              } max-w-md w-full pointer-events-auto alert alert-success hover:cursor-pointer`}
              onClick={() => toast.dismiss(t.id)}
            >
              <CheckmarkIcon />
              <p className="text-base-content">{successLabel}</p>
            </div>
          );
        });
      }
    } catch (e) {
      if (errorLabel) {
        toast.custom(t => {
          return (
            <div
              className={`${
                t.visible ? 'animate-enter' : 'animate-leave'
              } max-w-md w-full pointer-events-auto alert alert-error hover:cursor-pointer`}
              onClick={() => toast.dismiss(t.id)}
            >
              <ErrorIcon />
              <p>{errorLabel}</p>
            </div>
          );
        });
      }
    }
  };

  return (
    <button type="button" role="button" onClick={handlerClick} {...attrs}>
      {children}
    </button>
  );
}

See also

Favorite site

author Zer0 sitemap