JSFiddle - React, Tailwind, and code Playground

by romantonoff

HTML

<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@ionic/core/css/ionic.bundle.css">
<script src="https://unpkg.com/cupertino-pane@1.2.82/dist/cupertino-pane.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@ionic/core/dist/ionic/ionic.js"></script>
<html mode="ios">
<body class="dark">
<ion-app>
  <ion-content scroll-y="false">
      <!-- 1 -->
      <ion-notification id="id-1" onclick="closeNotification(1)">
        <div class="container">
            <div class="img">
              <svg aria-hidden="true" role="presentation" data-slug-id="three-dimensional" viewBox="0 0 48 48" xmlns="http://www.w3.org/2000/svg">
                <path d="M0 0V10.1053H5.05263V5.05263H10.1053V0H0Z" fill="#0078D4"></path>
                <path d="M37.8945 0V5.05263H42.9472V10.1053H47.9998V0H37.8945Z" fill="#0078D4"></path>
                <path d="M5.05263 37.8948H0V48H10.1053V42.9474H5.05263V37.8948Z" fill="#0078D4"></path>
                <path d="M42.9472 42.9474H37.8945V48H47.9998V37.8948H42.9472V42.9474Z" fill="#0078D4"></path>
                <path d="M24.2106 22.2401L36.7833 15.2506L24.0254 7.89062L11.377 15.1917L24.0506 22.2401H24.2106Z" fill="#50E6FF"></path>
                <path d="M10.1982 17.4219V31.8471L22.7288 39.0808V24.3945L10.1982 17.4219Z" fill="#50E6FF"></path>
                <path d="M37.8612 17.543L25.2549 24.5493V39.1261L37.8612 31.8503V17.543Z" fill="#50E6FF"></path>
              </svg>
            </div>
            <div class="text">
              <ion-text>One instance for all</ion-text>
              <small>New method to create a software: create and govern the one only strong and configurable instance, instead of weak spread.</small>
            </div>
          </div>
      </ion-notification>
      <!-- 2 -->
      <ion-notification id="id-2" onclick="closeNotification(2)">
        <div class="container">
            <div class="img">
              <svg aria-hidden="true" role="presentation" data-slug-id="charts-rise" viewBox="0...

CSS

body.dark {
    --cupertino-pane-icon-close-color: #a8a7ae;
    --cupertino-pane-background: #1c1c1d;
    --cupertino-pane-color: #ffffff;
    --cupertino-pane-shadow: 0 4px 16px rgb(0 0 0 / 12%);
    --cupertino-pane-border-radius: 20px;
    --cupertino-pane-move-background: #424246;
    --cupertino-pane-destroy-button-background: #424246;
    --ion-background-color: #1a1b20;
    --ion-background-color-rgb: rgb(26, 27, 32);
    --ion-color-primary: #0078d4;
}

  .cupertino-pane-wrapper .pane {
    border-radius: 10px !important;
    background: rgba(0,0,0,.3);
    backdrop-filter: saturate(180%) blur(20px);
    -webkit-backdrop-filter: saturate(180%) blur(20px);
    width: 94%;
    max-width: 390px;
    box-shadow: 0 -30px 80px 0 rgb(0 0 0 / 30%);
  }

  .cupertino-pane-wrapper .pane ion-notification {
    width: 100%; 
  }

  ion-notification {
    display: block;
    width: 94%;
    max-width: 390px;
    visibility: hidden;
  }

  ion-notification .container {
      display: flex;
      margin-left: 20px;
      margin-right: 20px;
  }

  ion-notification .text {
      display: flex;
      flex-direction: column;
      margin-left: 15px;
  }

  ion-notification ion-text {
      color: #ffffff;
      font-weight: 600;
  }

  ion-notification small {
      margin-top: 8px;
      color: rgb(213,213,213);
      display: block;
  }

  ion-notification .img {
      flex-shrink: 0;
      display: block;
      width: 30px;
      margin-top: 5px;
  }

  ion-notification svg {
    display: block;
  }

  .bottom-content {
    position: absolute;
    bottom: 80px;
    width: calc(100% - 40px);
          max-width: 390px;
    left: 0;
    right: 0;
    margin-left: auto;
    margin-right: auto;
    height: 190px;
    justify-content: space-between;
    display: flex;
    flex-direction: column;
    z-index: 1;
  }

  canvas {
    position: absolute;
    top: 220px;
    left: 80px;
  }

  .bottom-content h1 {
    font-size: 36px;
    font-weight: 600;
    color: #f4f5f6;
   ...

JavaScript

var notifications = {};
var marginBetween = 10;
var settings = { 
  inverse: true,
  breaks: {
    top: { enabled: true, bounce: true }
  },
  fitHeight:true,
  topperOverflow: false,
  bottomClose: true,
  buttonClose: false,
  showDraggable: false,
  upperThanTop: true,
  cssClass: 'notification'
};

// DOM ready
window.onload = async function () {
  await document.querySelector('ion-app').componentOnReady();
  await new Promise((resolve) => setTimeout(resolve, 250));
  for (let i = 1; i < 6; i++) {
    var elHeight = parseInt(document.defaultView.getComputedStyle(
      document.querySelector(`ion-notification#id-${i} .container`), 
    '').getPropertyValue('height'))
    console.log(`el - ${i} and height - ${elHeight}`);
    notifications[i] = { height: elHeight + 30 };

    // Add previous heights
    let heightPrevious = marginBetween;
    for (let j = 1; j < i; j++) {
      heightPrevious += notifications[j].height + marginBetween;
    }

    if (i < 5) {
      notifications[i].position = heightPrevious;  
    } else {
      notifications[i].position = 0;
    }
    let settingsExts = {
      bottomOffset: notifications[i].position, 
      onWillDismiss: () => onWillDismiss(i),
      ...settings
    };

    notifications[i].instance = new CupertinoPane('ion-notification#id-' + i, settingsExts);
    if (i < 5) {
      notifications[i].instance.present({animate: true});
    }
  }

  console.log('Notifications', notifications);
};

function onWillDismiss(id) {
  // get lower elements 
  let lowers = [];
  for (let i = 1; i < 6; i++) {
    if (notifications[i].position > notifications[id].position) {
      lowers.push(i);
    }
  }

  // reset position
  notifications[id].position = 0;

  // move to new positions
  for (let i = 0; i < lowers.length; i++) {
    let lowerId = lowers[i];
    // Previous heights
    let heightPrevious = marginBetween;
    for (let j = 1; j < 6; j++) {
      if (notifications[lowerId].position > notifications[j].position
        &&...