Tailwind Toasts

import React from "react";
import classnames from "classnames";

const styles = {
  error: {
    icon: "fad fa-exclamation-triangle text-red-500",
    bg: "bg-red-50",
    mainText: "text-red-800",
    subText: "text-red-700",
  },
  warning: {
    icon: "far fa-check-circle text-green-500",
  },
  success: {
    icon: "fas fa-check-circle text-green-900",
    bg: "bg-green-50",
    mainText: "text-green-800",
    subText: "text-green-700",
  },
};

const snackStates = {
  entering: {
    transform: "scale(0.8)",
    opacity: 0,
  },
  entered: {
    transform: "scale(1)",
    opacity: 1,
  },
  exiting: {
    transform: "scale(0.8)",
    opacity: 0,
  },
  exited: {
    transform: "scale(0.8)",
    opacity: 0,
  },
};

/**
 * @see https://tailwindui.com/components/application-ui/overlays/notifications
 */
export function TailwindToast({
  appearance = null,
  children,
  onDismiss,
  icon = null,
  subText = null,
  transitionState = null,
  transitionDuration,
}) {
  let bgClassName = "bg-white";
  let mainTextColor = "text-gray-900";
  let subTextColor = "text-gray-500";

  if (appearance) {
    icon = icon ?? styles[appearance]?.icon;
    bgClassName = styles[appearance]?.bg ?? bgClassName;
    mainTextColor = styles[appearance]?.mainText ?? bgClassName;
    subTextColor = styles[appearance]?.mainText ?? subTextColor;
  }

  return (
    <div
      className={classnames("shadow-lg rounded-lg pointer-events-auto mb-4", bgClassName)}
      style={{
        width: 380,
        transitionProperty: `transform opacity`,
        transitionDuration: `${transitionDuration}ms`,
        transitionTimingFunction: `cubic-bezier(0.2, 0, 0, 1)`,
        transformOrigin: "bottom",
        ...snackStates[transitionState],
      }}
    >
      <div className="rounded-lg shadow-xs overflow-hidden">
        <div className="p-4">
          <div className="flex items-start">
            {icon && (
              <div className="flex-shrink-0 text-lg">
                <i className={icon} />
              </div>
            )}
            <div className="ml-3 w-0 flex-1 pt-0.5">
              <p className={classnames("text-sm leading-5 font-medium", mainTextColor)}>{children}</p>
              {subText && <p className={classnames("mt-1 text-sm leading-5", subTextColor)}>{subText}</p>}
            </div>
            <div className="ml-4 flex-shrink-0 flex">
              <button
                className="inline-flex text-gray-400 focus:outline-none focus:text-gray-500 transition ease-in-out duration-150"
                onClick={() => onDismiss()}
              >
                <i className="far fa-times text-gray-400" />
              </button>
            </div>
          </div>
        </div>
      </div>
    </div>
  );
}
Made with by Rovak