JSFiddle - React, Tailwind, and code Playground

bottom panel prototype

by Travis Almand

HTML

<div id="content">
  <button id="test1_btn">test1</button>
  <button id="test2_btn">test2</button>
  <button id="test4_btn">test4</button>
</div>

<div id="test1" class="alk-bottom-panel">
  <p>bottom panel test 1</p>
  <p>this is a standard panel that will partially cover viewport</p>
  <p>click anywhere to close</p>
</div>

<div id="test2" class="alk-bottom-panel alk-bottom-panel-full">
  <div class="alk-bottom-panel-header">header</div>
  <p>bottom panel test 2</p>
  <p>full bottom panel with a button to open a third</p>
  <p>click header to close</p>
  
  <button id="test3_btn">test3</button>
</div>

<div id="test3" class="alk-bottom-panel">
  <div class="alk-bottom-panel-header">header</div>
  <p>bottom panel test 3</p>
  <p>this is a partial panel opened from the previous full panel</p>
  <p>click header to close</p>
</div>

<div id="test4a" class="alk-bottom-panel">
  <button id="test4b_btn">test4b</button>
  <button id="close4a_btn">close</button>
  <p>An example of swapping between two bottom panels.</p>
</div>
<div id="test4b" class="alk-bottom-panel">
  <button id="test4a_btn">test4a</button>
  <button id="close4b_btn">close</button>
  <p>An example of swapping between two bottom panels.</p>
</div>

SCSS

html,
body {
  margin: 0;
  padding: 0;
  height: 100%;
  transition: background-color 0.5s;
}

#content {
  background-color: #fff;
  height: 100%;
  transform: scale3d(1, 1, 1);
  transition: transform 0.5s;
}

.alk-bottom-panel {
  background-color: gainsboro;
  height: 100vh;
  left: 0;
  position: fixed;
  top: 0;
  transform: translate3d(0, 100%, 0);
  transition: 0.5s transform ease-in-out;
  width: 100vw;
  z-index: 1000;
}

.alk-bottom-panel-opened {
  transform: translate3d(0, 179px, 0);
  
  &.alk-bottom-panel-full {
    transform: translate3d(0, 0, 0);
  }
}

body.alk-bottom-panel-active {
  background-color: #333;
  
  #content {
    transform: scale3d(0.9, 0.9, 0.9);
  }
}

.alk-bottom-panel-blocker {
  background-color: rgba(0, 0, 0, 0.5);
  height: 100vh;
  left: 0;
  opacity: 0;
  position: fixed;
  top: 0;
  transition: width 0s 0.5s, opacity 0.5s;
  width: 0vw;
  z-index: 999;
  
  &.alk-bottom-panel-blocker-show {
    opacity: 1;
    transition: width 0s, opacity 0.5s;
    width: 100vw;
  }
}

JavaScript

document.querySelector('#test1_btn').addEventListener('click', function () { alkBottomPanel('#test1'); });
document.querySelector('#test1').addEventListener('click', function () { alkBottomPanel('#test1'); });
document.querySelector('#test2_btn').addEventListener('click', function () { alkBottomPanel('#test2'); });
document.querySelector('#test2 .alk-bottom-panel-header').addEventListener('click', function () {	alkBottomPanel('#test2'); })
document.querySelector('#test3_btn').addEventListener('click', function () { alkBottomPanel('#test3'); });
document.querySelector('#test3 .alk-bottom-panel-header').addEventListener('click', function () { alkBottomPanel('#test3'); })

document.querySelector('#test4_btn').addEventListener('click', function () { alkBottomPanel('#test4a'); });
document.querySelector('#test4a_btn').addEventListener('click', function () { alkBottomPanel('#test4a'); });
document.querySelector('#test4b_btn').addEventListener('click', function () { alkBottomPanel('#test4b'); });
document.querySelector('#close4a_btn').addEventListener('click', function () { alkBottomPanel('#test4a'); });
document.querySelector('#close4b_btn').addEventListener('click', function () { alkBottomPanel('#test4b'); });

function alkBottomPanel(element) {
	var $element = document.querySelector(element);
  var $body = document.body;
  var $blocker = document.querySelector('.alk-bottom-panel-blocker');
  var blockerElement;
  var openedBottomPanels;
  
  // check for blocker
  if ($blocker === null) {
    $body.insertAdjacentHTML('beforeend', '<div class="alk-bottom-panel-blocker"></div>');
    $blocker = document.querySelector('.alk-bottom-panel-blocker');
  }
  
  // check to make sure it's a valid element
  if ($element.classList.contains('alk-bottom-panel')) {
  	// check for active panel
    if (!document.querySelectorAll('.alk-bottom-panel-opened').length > 0 || $element.classList.contains('alk-bottom-panel-opened')) {
    	// there is no active panel or
      // active...