<body>
  <div id="root"></div>
</body>
/* Index */
body {
  margin: 0;
  padding: 0;
  font-family: sans-serif;
  background-color: #222;
}

/* App */
.App {
  text-align: center;
}

/* Header */
.Logo {
  animation: App-logo-spin infinite 20s linear;
  height: 80px;
}

.Header {
  background-color: #222;
  height: 150px;
  padding: 20px;
  color: white;
}

@keyframes App-logo-spin {
  from { transform: rotate(0deg); }
  to { transform: rotate(360deg); }
}

/* Button */
button {
    background-color: #306B7B;
    border: none;
    cursor: pointer;
    color: white;
    padding: 15px 32px;
    text-align: center;
    text-decoration: none;
    display: inline-block;
    font-size: 16px;
    margin-left: 10px;
}

.Button-alert {
  background-color: #AEA53B;
}

/* Notification Container */
.Notification-container {
  position: fixed;
  width: 320px;
  padding: 0 10px 10px;
  z-index: 1;
  box-sizing: border-box;
  height: auto;
  /* `Top-right` is the default */
  top: 0px;
  bottom: auto;
  left: auto;
  right: 0px;
}

.Bottom-right {
  top: auto;
  bottom: 0px;
  left: auto;
  right: 0px;
}

.Bottom-left {
  top: auto;
  bottom: 0px;
  left: 0px;
  right: auto;
}

.Top-left {
  top: 0px;
  bottom: auto;
  left: 0px;
  right: auto;
}

/* Notification */
.Info {
  position: relative;
  width: 100%;
  font-size: 16px;
  margin: 10px 0 0;
  padding: 10px;
  box-sizing: border-box;
  opacity: 1;
  transition: 0.3s ease-in-out;
  transform: translate3d(0px, 0px, 0px);
  will-change: transform, opacity;
  background: #ADEBFC;
  color: #2E6C7D; /* 50% darker http://www.hexcolortool.com */
}

.Alert {
  background: #FBF06C;
  color: #7C7100; /* 50% darker http://www.hexcolortool.com */
}

.Warning {
  background: #E26F53;
  color: #630000; /* 50% darker http://www.hexcolortool.com */
}

/* Modal */
.Modal {
  display: none;
  position: fixed;
  z-index: 1;
  left: 0;
  top: 0;
  width: 100%;
  height: 100%;
  overflow: auto;
  background-color: rgb(0,0,0);
  background-color: rgba(0,0,0,0.4);
}

/* background to close the modal when clicking outside of `Modal-content` */
.Modal-close {
  position: fixed;
  z-index: -1;
  width: 100%;
  height: 100%;
}

.Modal-content {
  background-color: #fefefe;
  margin: 15% auto;
  padding: 20px;
  width: 80%;
}

.Close {
  color: #aaa;
  float: right;
  font-size: 28px;
  font-weight: bold;
}

.Close:hover,
.Close:focus {
  color: black;
  text-decoration: none;
  cursor: pointer;
}
class App extends React.Component {
  constructor() {
    super();
    this.toggleMode = this.toggleMode.bind(this);
    this.addNotification = this.addNotification.bind(this);
    this.removeNotification = this.removeNotification.bind(this);
    this.state = {
      notificationArr: [],
      key: 0,
      modal: false
    };
  }

  toggleMode() {
    if (!this.state.modal) {
      this.removeAllNotifications();
    }
    this.setState(prevState => ({
      modal: prevState.modal = !prevState.modal
    }));
  }

  removeAllNotifications() {
    this.setState(prevState => ({
      notificationArr: prevState.notificationArr = []
    }));
  }

  showModal() {
    const modal = document.getElementById('SpecialModal');
    modal.style.display = 'block';
  }

  addNotification() {
    const notification =
      <Notification
        key={this.state.key}
        /*
          Define `props` values of your notification here.
          Choose the `type` prop between:
            - Alert (yellow)
            - Warning (red)

          If you don't set a `text`, `type` or `time` value, the default
          values will be active.
          The default value for `type` is: `Info` (blue).
          The default value for `text` is: `Lorem ipsum`.
          The default value for `time` is: `3000` (3s).
        */
        type=""
        text="Love in form of an notification"
        time="8000"
      />;

    // state updates may be asynchronous, so use the second form of `setState()`
    this.setState(prevState => ({
      // http://stackoverflow.com/questions/26253351/correct-modification-of-state-arrays-in-reactjs
      notificationArr: prevState.notificationArr.concat(notification),
      key: prevState.key + 1
    }));
    this.timeoutNotification(notification.props.time);
  }

  timeoutNotification(time) {
    const delay = time ? time : 3000;
    setTimeout(this.removeNotification, delay);
  }

  removeNotification() {
    const arr = this.state.notificationArr;
    const arrLength = arr.length;
    // Use `slice()` because it doesn't mutate the original array,
    // it's good for React state handling and functional programming.
    const newArr = arrLength ? arr.slice(0, arrLength - 1) : [];

    this.setState(prevState => ({
      notificationArr: prevState.notificationArr = newArr
    }));
  }

  render() {
    const notifications = this.state.notificationArr;
    const isModal = this.state.modal;

    return (
      <div className="App">
        <Header />
        {isModal ? (
          <div>
            <Button class="Button-alert" text="Notification Mode" onClick={this.toggleMode} />
            <Button text="React Modal" onClick={this.showModal} />
            <Modal />
          </div>
        ) : (
          <div>
            <Button class="Button-alert" text="Modal Mode" onClick={this.toggleMode} />
            <Button text="React Notification" onClick={this.addNotification} />
            <NotificationContainer
              /*
                Define the `position` of the notification here.
                Choose between:
                  - Bottom-right
                  - Bottom-left
                  - Top-left

                If you don't set a value, the default value: `Top-right`
                will be active.
              */
              position="Top-left">
              {notifications}
            </NotificationContainer>
          </div>
        )}
      </div>
    );
  }
}

class Header extends React.Component {
  render() {
    return (
      <div className="Header">
        <img src="https://agile-basin-61855.herokuapp.com/static/media/logo.5d5d9eef.svg" className="Logo" alt="logo" />
      </div>
    );
  }
}

class Button extends React.Component {
  render() {
    return (
      <button className={this.props.class} onClick={this.props.onClick}>
        {this.props.text}
      </button>
    );
  }
}

class NotificationContainer extends React.Component {
  render() {
    const position = this.props.position ? ' ' + this.props.position : '';

    return (
      <div className={"Notification-container" + position}>
        {this.props.children}
      </div>
    );
  }
}

class Notification extends React.Component {
  render() {
    const type = this.props.type ? ' ' + this.props.type : '';
    const text = this.props.text ? this.props.text : 'Lorem ipsum';

    return (
      <div className={"Info" + type}>
        <p>{text}</p>
      </div>
    );
  }
}

class Modal extends React.Component {
  hideModal() {
    const modal = document.getElementById('SpecialModal');
    modal.style.display = 'none';
  }

  render() {
    return (
      <div id="SpecialModal" className="Modal">
        <div className="Modal-close" onClick={this.hideModal}></div>
        <div className="Modal-content">
          <span className="Close" onClick={this.hideModal}>&times;</span>
          <p>A very interesting message in a large nice modal</p>
        </div>
      </div>
    );
  }
}

ReactDOM.render(
  <App />,
  document.getElementById('root')
);
View Compiled

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

  1. https://cdnjs.cloudflare.com/ajax/libs/react/15.4.2/react.min.js
  2. https://cdnjs.cloudflare.com/ajax/libs/react/15.4.2/react-dom.min.js