JSFiddle - React, Tailwind, and code Playground

bottom panel prototype jquery

by Travis Almand

HTML

<div id="content">
  <button id="test1_btn">test1</button>
  <button id="test2_btn">test2</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>

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

$('#test1_btn').on('click', function () { $('#test1').alkBottomPanel(); });
$('#test1').on('click', function () { $('#test1').alkBottomPanel(); });

$('#test2_btn').on('click', function () { $('#test2').alkBottomPanel(); });
$('#test2 .alk-bottom-panel-header').on('click', function () {
	$('#test2').alkBottomPanel();
})

$('#test3_btn').on('click', function () { $('#test3').alkBottomPanel(); });
$('#test3 .alk-bottom-panel-header').on('click', function () { $('#test3').alkBottomPanel(); })

$.fn.alkBottomPanel = function() {
  return this.each(function () {
    var $this = $(this);
    var $body = $('body');
    var $blocker = $('.alk-bottom-panel-blocker');
    
    // check for blocker
    if ($blocker.length === 0) {
      $body.append('<div class="alk-bottom-panel-blocker"></div>');
      $blocker = $('.alk-bottom-panel-blocker');
    }

		// delay to allow for blocker creation if needed
		window.setTimeout(function () {
      // check to make sure it's a valid element
      if ($this.hasClass('alk-bottom-panel')) {
      	// check for active panel
      	if (!$('.alk-bottom-panel-opened').length > 0 || $this.hasClass('alk-bottom-panel-opened')) {
        	// there is no active panel or
          // active panel is the one just set in motion
          // therefore toggle classes as expected
          $body.toggleClass('alk-bottom-panel-active');
          $blocker.toggleClass('alk-bottom-panel-blocker-show');
          $this.toggleClass('alk-bottom-panel-opened');
        } else {
        	// there is an active panel as new one is activated
          // hide initial panel
        	$('.alk-bottom-panel-opened').removeClass('alk-bottom-panel-opened');
          // show newly activated panel
          $this.addClass('alk-bottom-panel-opened');
        }
      }
    }, 100);
  });
};