<div class="toaster">
  <form name="toaster-controls">
    <fieldset class="toast-types">
      <button class="add-toast" type="button">Add Toast</button>
      <label><input type="radio" name="toast-type" checked value="success" /> Success</label>
      <label><input type="radio" name="toast-type"  value="failure" /> Failure</label>
      <label><input type="radio" name="toast-type"  value="warning" /> Warning</label>
      <label><input type="radio" name="toast-type" value="default" /> Default</label>      
    </fieldset>
  </form>
</div>
body {
  margin: 0;
  padding: 0;
  font-family: Roboto, Arial, sans-serif;
  background-color: #fddfdd;
}

/* Toaster Controls Style */
form[name="toaster-controls"] {
  position: absolute;

  .toast-types {
    display: flex;
    flex-direction: column;
    border: none;

    .add-toast {
      font-size: inherit;
      margin: 0.25rem;
      border: none;
      border-radius: 0.25rem;
      color: #fdfdfd;
      padding: 0.5rem;
      background-color: #000;
      cursor: pointer;
    }
  }
}

/* Toast Message Styles */
.toast {
  position: relative;
  display: flex;
  justify-content: center;
  align-items: center;
  min-width: 8rem;
  max-width: 8rem;
  min-height: 1.5rem;
  border-radius: 0.5rem;
  margin-left: auto;
  margin-right: auto;
  color: #fdfdfd;
  background-color: #000000;
  padding: 0.25rem;
  box-sizing: border-box;
  opacity: 0;
  transition: opacity 0.35s ease-in;

  @media screen and (min-width: 1025px) {
    min-width: 10rem;
    max-width: 12rem;
  }
  
  @media screen and (min-width: 1280px) {
    max-width: 15rem;    
  }

  .toast-button {
    color: #fdfdfd;

    &::after {
      cursor: pointer;
      position: absolute;
      font-size: 0.7em;
      top: 0;
      right: 0;
      padding: 0.3rem;
      padding-top: 0;
      content: "x";
      outline: inherit;
    }
  }

  .toast-button:hover {
    color: gray;
  }

  &.success {
    background-color: #1e8e68;
  }

  &.warning {
    background-color: #ff8c00;
  }

  &.failure {
    background-color: #8b0000;
  }
  
  &.appear {
    opacity: 1;
  }
}

.toaster {
  position: relative;

  .toast {
    margin-top: 0.25rem;
  }
}
const toastType = Object.freeze({
  default: "",
  success: "success",
  failure: "failure",
  warning: "warning"
});

class Toaster {
  constructor(toasterSelector) {
    this.toaster = document.querySelector(toasterSelector);
    this.removeToastListener = event => {
      const toastButton = event.target;

      this.removeToast(toastButton);
    };

    this.removeKeyboardToastListener = event => {
      if (event.key === "Enter") {
        this.removeToastListener(event);
      }
    };

    this.toaster.addEventListener("click", this.removeToastListener);
    this.toaster.addEventListener("keydown", this.removeKeyboardToastListener);
  }

  dispose() {
    this.toaster.removeEventListener("click", this.removeToastListener);
    this.toaster.removeEventListener(
      "keydown",
      this.removeKeyboardToastListener
    );
    this.toaster.parentNode.removeChild(this.toaster);
  }

  removeToast(toastButton) {
    const toast = toastButton.parentNode;

    if (
      toast.parentNode === this.toaster &&
      toastButton.classList.contains("toast-button")
    ) {
      toast.parentNode.removeChild(toast);
    }
  }

  addToast(content, type = toastType.default) {
    const toast = Object.assign(document.createElement("div"), {
      className: `toast ${type}`,
      innerText: content
    });

    const toastButton = Object.assign(document.createElement("div"), {
      className: `toast-button`,
      tabIndex: 0
    });

    toast.appendChild(toastButton);

    this.toaster.appendChild(toast);

    setTimeout(() => {
      toast.classList.add("appear");
    }, 40);
  }
}

(() => {
  const toaster = new Toaster(".toaster");

  toaster.addToast("success", toastType.success);
  toaster.addToast("failure", toastType.failure);
  toaster.addToast("warning", toastType.warning);
  toaster.addToast("default");

  document.querySelector(".toaster .add-toast").addEventListener("click", e => {
    const selectedToastType =
      document.forms["toaster-controls"].elements["toast-type"].value;

    toaster.addToast(`${selectedToastType}`, toastType[selectedToastType]);
  });
})();

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.