React-toastify: Use completely custom toast instead of overwriting classes etc.

Created on 9 Apr 2020  ยท  12Comments  ยท  Source: fkhadra/react-toastify

I'd really like to use my own completely styled toast component and just use the toastify api to display/close it. It doesn't seem like this is possible (didn't find anything in the docs), is there a way to do it?

feature

Most helpful comment

Toast.tsx

import React from 'react'
import styles from './toast.module.css'
import successIcon from './images/greentick.svg'
import errorIcon from './images/redalert.svg'
import closeIcon from './images/closebutton.svg'
export declare type ToastType = 'info' | 'success' | 'error'

interface Props {
  message: string
  type: ToastType
}

const Toast: React.SFC<Props> = (props) => {
  return (
    <div
      className={styles.container}
      style={{ borderColor: props.type === 'success' ? '#27AE60' : '#EB5757' }}
    >
      <div className={styles.flex}>
        <div>
          <img src={props.type === 'success' ? successIcon : errorIcon} />
        </div>
        <p className={styles.message}>{props.message}</p>
        <div className={styles.closeButton}>
          <img src={closeIcon} />{' '}
        </div>
      </div>
    </div>
  )
}

export default Toast

toast.module.css

.container {
  padding: 20px 16px;
  background: #333;
  width: 100%;
  border-left: solid 4px #27ae60;
}

.flex {
  display: flex;
  flex-direction: row;
  justify-content: flex-start;
  align-items: center;
  font-size: 16px;
  font-family: Open Sans;
}

.message {
  padding: 0px 16px;
  margin: 0px;
  color: #fff;
}

.closeButton {
  margin-left: auto;
}

In app.css

.Toastify__toast {
  border-radius: 4px;
  background-color: #333;
  padding: 0px;
}

.Toastify__toast-container {
  width: min(400px, 100vw);
}

Finally,

import React from 'react'
import { toast, ToastOptions, Slide } from 'react-toastify'
import ToastUI, { ToastType } from './Toast'

const toastOptions: ToastOptions = {
  position: 'top-center',
  autoClose: 10000,
  hideProgressBar: true,
  closeOnClick: true,
  pauseOnHover: true,
  draggable: true,
  progress: undefined,
  transition: Slide,
  rtl: false,
  closeButton: false,
}

export const sendNotification = (message: string, type: ToastType) => {
  toast(<ToastUI message={message} type={type} />, toastOptions)
}

cc @fkhadra

All 12 comments

For the moment the only way is to write your own css. But with the v6 coming soon https://github.com/fkhadra/react-toastify/pull/432 this will be possible

Ah wow, that's good to know, thank you! Really looking forward to v6

100% Agree. Overwriting everything is a huge mess.
@fkhadra How does v6 solve this?

You don't have to overwrite everything. Just build yours from scratch.

import 'react-toastify/dist/ReactToastify.minimal.css';

Build yours:

/** Used to define container behavior: width, position: fixed etc... **/
.Toastify__toast-container {
}

/** Used to define the position of the ToastContainer **/
.Toastify__toast-container--top-left {
}
.Toastify__toast-container--top-center {
}
.Toastify__toast-container--top-right {
}
.Toastify__toast-container--bottom-left {
}
.Toastify__toast-container--bottom-center {
}
.Toastify__toast-container--bottom-right {
}

/** Classes for the displayed toast **/
.Toastify__toast {
}
.Toastify__toast--rtl {
}
.Toastify__toast--dark {
}
.Toastify__toast--default {
}
.Toastify__toast--info {
}
.Toastify__toast--success {
}
.Toastify__toast--warning {
}
.Toastify__toast--error {
}
.Toastify__toast-body {
}

/** Classes for the close button. Better use your own closeButton **/
.Toastify__close-button {
}
.Toastify__close-button--default {
}
.Toastify__close-button > svg {
}
.Toastify__close-button:hover, .Toastify__close-button:focus {
}

/** Classes for the progress bar **/
.Toastify__progress-bar {
}
.Toastify__progress-bar--animated {
}
.Toastify__progress-bar--controlled {
}
.Toastify__progress-bar--rtl {
}
.Toastify__progress-bar--default {
}
.Toastify__progress-bar--dark {
}

You also have an example here
Edit react-styled-components-toastify transition issue

If you are comfortable with sass.
Grab the scss directory of the repository and build your own stylesheet. If you just want to changes some colors most of them are defined inside the _variables.scss file.

โ”œโ”€โ”€ _closeButton.scss
โ”œโ”€โ”€ _progressBar.scss
โ”œโ”€โ”€ _toast.scss
โ”œโ”€โ”€ _toastContainer.scss
โ”œโ”€โ”€ _variables.scss
โ”œโ”€โ”€ ๐Ÿ“ animations
โ”‚  โ”œโ”€โ”€ _bounce.scss
โ”‚  โ”œโ”€โ”€ _flip.scss
โ”‚  โ”œโ”€โ”€ _slide.scss
โ”‚  โ””โ”€โ”€ _zoom.scss
โ”œโ”€โ”€ main.scss
โ””โ”€โ”€ minimal.scss

Hope this can help

It's already 6.0.2 and I can't see the ability to swap toast component for custom one, am I missing something, or feature was cancelled ?

Hello @hrytskivr,

2 new hooks are expose useToast and useToastContainer. Unfortunatelly this is not documented yet how to use them. I'm still thinking about the usability

I have created my own custom toast @hrytskivr @agcty
image

Hey @nihalanisumit, looks awesome, do you mind sharing the source if possible ?

EDIT: @itayganor I'm interested by the style here

@fkhadra as far as I understand you are the maintainer. Yeah I know that it is not documented yet but it is implemented already and can be used and the API will not be changed? Thanks.

@pavelspichonak indeed I'm the maintainer and the author of the library. It's not documented yet cause I need to find time to do it. I don't expect the API to change that much, I would prefer to simplify it a bit.

If you are interested you can check how ToastContainer and Toast component are implemented.

Toast.tsx

import React from 'react'
import styles from './toast.module.css'
import successIcon from './images/greentick.svg'
import errorIcon from './images/redalert.svg'
import closeIcon from './images/closebutton.svg'
export declare type ToastType = 'info' | 'success' | 'error'

interface Props {
  message: string
  type: ToastType
}

const Toast: React.SFC<Props> = (props) => {
  return (
    <div
      className={styles.container}
      style={{ borderColor: props.type === 'success' ? '#27AE60' : '#EB5757' }}
    >
      <div className={styles.flex}>
        <div>
          <img src={props.type === 'success' ? successIcon : errorIcon} />
        </div>
        <p className={styles.message}>{props.message}</p>
        <div className={styles.closeButton}>
          <img src={closeIcon} />{' '}
        </div>
      </div>
    </div>
  )
}

export default Toast

toast.module.css

.container {
  padding: 20px 16px;
  background: #333;
  width: 100%;
  border-left: solid 4px #27ae60;
}

.flex {
  display: flex;
  flex-direction: row;
  justify-content: flex-start;
  align-items: center;
  font-size: 16px;
  font-family: Open Sans;
}

.message {
  padding: 0px 16px;
  margin: 0px;
  color: #fff;
}

.closeButton {
  margin-left: auto;
}

In app.css

.Toastify__toast {
  border-radius: 4px;
  background-color: #333;
  padding: 0px;
}

.Toastify__toast-container {
  width: min(400px, 100vw);
}

Finally,

import React from 'react'
import { toast, ToastOptions, Slide } from 'react-toastify'
import ToastUI, { ToastType } from './Toast'

const toastOptions: ToastOptions = {
  position: 'top-center',
  autoClose: 10000,
  hideProgressBar: true,
  closeOnClick: true,
  pauseOnHover: true,
  draggable: true,
  progress: undefined,
  transition: Slide,
  rtl: false,
  closeButton: false,
}

export const sendNotification = (message: string, type: ToastType) => {
  toast(<ToastUI message={message} type={type} />, toastOptions)
}

cc @fkhadra

This example is not working for me. Is it possible to get some official docs on how to do this?

Was this page helpful?
0 / 5 - 0 ratings

Related issues

jorgecuesta picture jorgecuesta  ยท  5Comments

fkhadra picture fkhadra  ยท  4Comments

nirsky picture nirsky  ยท  3Comments

AiBaby19 picture AiBaby19  ยท  4Comments

spiritedfang picture spiritedfang  ยท  3Comments