{"id":402437,"date":"2024-06-29T16:30:08","date_gmt":"2024-06-29T16:30:08","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=402437"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=402437","title":{"rendered":"<span>[Dribbble Challenge] \u2014 Coffee Ordering Animation<\/span>"},"content":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-1\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<h4 id=\"tutorial-level-beginnerjunior\">Tutorial level: Beginner\/Junior<\/h4>\n<p>  <\/p>\n<h3 id=\"motivation\">Motivation<\/h3>\n<p>  <\/p>\n<p>Sometimes, when we surf dribbble, uplabs and similar design clouds, we often find many concepts or prototypes with animations, micro interactions, application flow and so on.<br \/>  I often find illustrations of mobile apps that are good and interesting, but of course they are still in the form of concept, so therefore, why don&#8217;t we try to apply them as an interface for applications that we will build next.<\/p>\n<p>  <\/p>\n<h3 id=\"original-concept\">Original concept<\/h3>\n<p>  <\/p>\n<p>In the Dribbble Challenge we will try to build an interface for <a href=\"https:\/\/dribbble.com\/shots\/6372790-Coffee-Ordering-Animation-Starbucks\">Coffee Ordering<\/a>, as I found on Dribble.<\/p>\n<p>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/pb\/t8\/nc\/pbt8ncbyhpo9hbwn3ecgeh32zyy.png\" data-src=\"https:\/\/habrastorage.org\/webt\/pb\/t8\/nc\/pbt8ncbyhpo9hbwn3ecgeh32zyy.png\"\/>  <\/p>\n<p><a href=\"https:\/\/dev-to-uploads.s3.amazonaws.com\/i\/autk6139mcjra1ic0s8w.gif\"><em>GIF here<\/em><\/a><\/p>\n<p><a name=\"habracut\"><\/a>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/dev-to-uploads.s3.amazonaws.com\/i\/autk6139mcjra1ic0s8w.gif\" alt=\"Alt Text\" data-src=\"https:\/\/dev-to-uploads.s3.amazonaws.com\/i\/autk6139mcjra1ic0s8w.gif\"\/><\/p>\n<p>  <\/p>\n<h4 id=\"the-flow-is-quite-simple\">The flow is quite simple:<\/h4>\n<p>  <\/p>\n<ul>\n<li>User will choose the size of glass<\/li>\n<li>User will place the order to basket<\/li>\n<li>User redirected to the checkout page<\/li>\n<\/ul>\n<p>  <\/p>\n<h4 id=\"technologies\">Technologies<\/h4>\n<p>  <\/p>\n<p>We will use quite simple technologies stack: <strong>HTML<\/strong> + <strong>CSS<\/strong> + <strong>JavaScript<\/strong>.<br \/>  Final result can be fit in just one <code>html<\/code> file.<br \/>  Of course, you can use <strong>SCSS<\/strong>, <strong>TypeScript<\/strong>, <strong>React<\/strong>, <strong>Angular<\/strong> and other tools, but the target of tutorial just a simplest interface demonstration. <\/p>\n<p>  <\/p>\n<h4 id=\"packages\">Packages<\/h4>\n<p>  <\/p>\n<p>We also will using 2 additional packages:<\/p>\n<p>  <\/p>\n<ul>\n<li><a href=\"http:\/\/ionicframework.com\">Ionic Framework<\/a> \u2014 Mobile interfaces and components library<\/li>\n<li><a href=\"https:\/\/github.com\/roman-rr\/cupertino-pane\">Cupertino Pane<\/a> \u2014 Touch panes and transitions<\/li>\n<\/ul>\n<p>  <\/p>\n<h3 id=\"lets-build\">Let&#8217;s Build<\/h3>\n<p>  <\/p>\n<p>Firstly, create a simple <code>index.html<\/code> file in any new folder.<br \/>  Open file and write default required tags<\/p>\n<p>  <\/p>\n<pre><code class=\"html\">&lt;!DOCTYPE html> &lt;html>   &lt;head>     &lt;meta charset=\"UTF-8\">     &lt;title>Coffee Ordering&lt;\/title>     &lt;style>      &lt;!-- Styles will be placed here -->    &lt;\/style>   &lt;\/head>   &lt;body>      &lt;script>      &lt;!-- Scripts will be placed here -->     &lt;\/script>   &lt;\/body> &lt;\/html><\/code><\/pre>\n<p>  <\/p>\n<p>I hope you already familiar with html tags and attributes above. If so, continue next, otherwise, take a quick look of <a href=\"https:\/\/www.w3schools.com\/tags\/ref_byfunc.asp\">html guidelines<\/a><\/p>\n<p>  <\/p>\n<h4 id=\"libraries-installation\">Libraries installation<\/h4>\n<p>  <\/p>\n<p>In this step we inject some libraries to our page. Add some lines to your <code>&lt;head><\/code><\/p>\n<p>  <\/p>\n<pre><code class=\"html\">&lt;head>     &lt;meta charset=\"UTF-8\">     &lt;title>Coffee Ordering&lt;\/title>      &lt;meta name=\"viewport\" content=\"viewport-fit=cover, width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no\">     &lt;script>var exports = {\"__esModule\": true};&lt;\/script>     &lt;script type=\"module\" src=\"https:\/\/cdn.jsdelivr.net\/npm\/@ionic\/core\/dist\/ionic\/ionic.esm.js\">&lt;\/script>     &lt;script nomodule src=\"https:\/\/cdn.jsdelivr.net\/npm\/@ionic\/core\/dist\/ionic\/ionic.js\">&lt;\/script>     &lt;script src=\"https:\/\/unpkg.com\/cupertino-pane\/dist\/cupertino-pane.min.js\">&lt;\/script>     &lt;link rel=\"stylesheet\" href=\"https:\/\/cdn.jsdelivr.net\/npm\/@ionic\/core\/css\/ionic.bundle.css\"\/>      &lt;style>      &lt;!-- Styles will be placed here -->    &lt;\/style> &lt;\/head><\/code><\/pre>\n<p>  <\/p>\n<p>Note, that we are using all libraries from CDN and then, keep files locally isn&#8217;t required. <\/p>\n<p>  <\/p>\n<p>Tag <code>&lt;meta name=\"viewport\"><\/code> gives the browser instructions on how to control the page&#8217;s dimensions and scaling.<\/p>\n<p>  <\/p>\n<p>And declaration of exports <code>var exports = {\"__esModule\": true};<\/code> will resolve some libraries\/environments variable scope issues. <\/p>\n<p>  <\/p>\n<p>With these all libraries are installed and we can going to developing. <\/p>\n<p>  <\/p>\n<h4 id=\"first-page-state-dom-elements\">First page state DOM elements<\/h4>\n<p>  <\/p>\n<p>Let&#8217;s add some new elements into our <code>&lt;body><\/code> tag.<\/p>\n<p>  <\/p>\n<pre><code class=\"html\">&lt;body>   &lt;ion-app>   &lt;ion-content scroll-y=\"false\">   &lt;div class=\"content\">     &lt;ion-header translucent=\"true\">       &lt;ion-toolbar>         &lt;ion-buttons slot=\"start\">           &lt;ion-button>             &lt;ion-icon name=\"chevron-back-outline\">&lt;\/ion-icon>             Frappuccino           &lt;\/ion-button>         &lt;\/ion-buttons>         &lt;ion-buttons slot=\"end\">           &lt;ion-button>             &lt;ion-icon name=\"heart-outline\">&lt;\/ion-icon>           &lt;\/ion-button>         &lt;\/ion-buttons>       &lt;\/ion-toolbar>     &lt;\/ion-header>     &lt;div class=\"content-body\">       &lt;img src=\"https:\/\/raw.githubusercontent.com\/roman-rr\/cupertino-pane\/master\/playground\/img\/starbucks.png\" \/>       &lt;h1>Mocha Frappuccino&lt;\/h1>       &lt;p>         Buttery caramel syrup meets coffee, milk and ice for a rendezvous in the blender.       &lt;\/p>       &lt;div class=\"line\">         &lt;div class=\"price\">           \u00a3            &lt;div class=\"big\">3&lt;\/div>           .45         &lt;\/div>         &lt;div class=\"sizes\">           &lt;div class=\"active-frame\">&lt;\/div>           &lt;div class=\"size active\" onclick=\"setActive(this, 3, 0, 'S')\">             S             &lt;ion-icon name=\"cafe-outline\">&lt;\/ion-icon>           &lt;\/div>           &lt;div class=\"size\" onclick=\"setActive(this, 5, 1, 'M')\">             M             &lt;ion-icon name=\"cafe-outline\">&lt;\/ion-icon>           &lt;\/div>           &lt;div class=\"size\" onclick=\"setActive(this, 7, 2, 'L')\">             L             &lt;ion-icon name=\"cafe-outline\">&lt;\/ion-icon>           &lt;\/div>         &lt;\/div>       &lt;\/div>       &lt;ion-button id=\"button-add\"         expand=\"block\"          onclick=\"presentPane();\">         &lt;span class=\"button-text\">Add to Bag&lt;\/span>         &lt;ion-icon name=\"checkmark-outline\">&lt;\/ion-icon>       &lt;\/ion-button>       &lt;div class=\"draggable\">         &lt;div class=\"move\">&lt;\/div>       &lt;\/div>     &lt;\/div>   &lt;\/div>   &lt;ion-content>   &lt;ion-app> &lt;\/body><\/code><\/pre>\n<p>  <\/p>\n<p>All images we will using from CDN also. So, no any more local files needed and tests should be simple. <\/p>\n<p>  <\/p>\n<h4 id=\"first-page-state-styles\">First page state styles<\/h4>\n<p>  <\/p>\n<p>Add some styles into your <code>&lt;head><\/code>.<br \/>  Styles will describe product information and size picker style. <\/p>\n<p>  <\/p>\n<pre><code class=\"css\">ion-toolbar {   --background: #ffffff;   --border-color: #ffffff; }  ion-content {   --background: rgb(0, 112, 74); }  .content {   background: #ffffff;   height: 100%;   border-radius: 0 0 30px 30px;   border-width: 1px;   border: 1px solid #ffffff; }  ion-toolbar ion-button {   --color: #292929; }  .content-body {   padding-left: 20px;   padding-right: 20px; }  .content-body h1 {   margin-top: 30px; }  .content-body p {   color: #828282;   font-size: 14px;   line-height: 20px; }  .content-body img {   display: block;   max-width: 100%;   margin: auto;   margin-top: 10px; }  .content-body ion-button {   margin-left: 0;   margin-right: 0;   --border-radius: 30px;   font-weight: 600;   --background: rgb(0, 112, 74);   margin-top: 15px; }  .content-body ion-button:active {   --background: rgb(39, 92, 65); }  .content-body .price {   display: flex;   align-items: center;   font-size: 26px;   font-weight: 600;   height: 60px;   margin-left: 5px; }  .content-body .price .big {   margin-left: 5px;   font-size: 50px; }  .content-body .line {   height: 60px;   display: flex;   justify-content: space-between;   align-items: center;   flex-direction: row; }  .content-body .sizes {    display: flex; }  .content-body .sizes .size {   font-size: 11px;   font-weight: 700;   display: flex;   justify-content: center;   align-items: center;   width: 48px;   height: 48px;   border: 1px solid #DADADA;   border-radius: 3px;   margin-right: 7px;   color: #DADADA;   background: rgb(248, 248, 248);   padding-bottom: 3px;   transition: all 200ms ease-in-out;   position: relative; }      .content-body .sizes .size.active {   font-size: 11px;   background: rgb(232, 240, 236);   color: rgb(48, 111, 78); }  .content-body .sizes .active-frame {   transform: translate3d(0px, 0px, 0px);   transition: all 200ms ease-in-out;   border-radius: 3px;   width: 48px;   height: 48px;   position: absolute;   border: 2px solid rgb(48, 111, 78);   z-index: 2; }  .content-body .sizes .size ion-icon {   position: absolute;   font-size: 37px;   margin-top: 6px;   top: 0;   left: 2px;   right: 0;   margin-left: auto;   margin-right: auto;   z-index: 1; }  .content-body .draggable {   padding: 15px;    position: absolute;    bottom: 0px;    left: 0px;    right: 0px;    margin-left: auto;    margin-right: auto;    height: 30px; }  .content-body .draggable .move {   margin: 0px auto;    height: 5px;    background: rgba(202, 202, 202, 0.6);    width: 50px;    border-radius: 4px;    backdrop-filter: saturate(180%) blur(20px); }<\/code><\/pre>\n<p>  <\/p>\n<p>Open <code>index.html<\/code> file in browser and check what we got:<\/p>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/dev-to-uploads.s3.amazonaws.com\/i\/1tnydd500payd6k4cil9.png\" alt=\"Alt Text\" data-src=\"https:\/\/dev-to-uploads.s3.amazonaws.com\/i\/1tnydd500payd6k4cil9.png\"\/><\/p>\n<p>  <\/p>\n<h4 id=\"size-picker\">Size picker<\/h4>\n<p>  <\/p>\n<p>On this step, first interface statement should be prepared well. Styles are applied and we can make first interaction works \u2014 picking a drink size.<br \/>  Time to add some scripts into our <code>&lt;script><\/code> tag.<\/p>\n<p>  <\/p>\n<pre><code class=\"javascript\">&lt;script>   function setActive(e, n, kfc, s) {     itemprice = n;     size = s;     let frame = document.querySelector('.active-frame ');     frame.style.transform = `translate3d(${55 * kfc}px, 0px, 0px)`;      let elems = document.getElementsByClassName('size');     for (var i = 0; i &lt; elems.length; i++) {       elems[i].classList.remove('active');     }     e.classList.add('active');     document.getElementsByClassName('big')[0].innerHTML = itemprice;   } &lt;\/script><\/code><\/pre>\n<p>  <\/p>\n<p>Now you can pick any drink size, frame will be moved according with css <code>tranform\/transition<\/code> options, and price is also will be changed dynamically. <\/p>\n<p>  <\/p>\n<h4 id=\"add-to-bag\">Add to Bag<\/h4>\n<p>  <\/p>\n<p>We need to handle &#171;Add to Bag&#187; button and Pane opening. <\/p>\n<p>  <\/p>\n<p>Important part to understand is how we imitate pane behavior on our first state content. True moving pane will be appears from bottom, but our content is just &#171;follower&#187; of bottom pane transitions. To imitate this behavior we are intentionally rounded bottom corners of our content and unrounded pane corners.<\/p>\n<p>  <\/p>\n<h4 id=\"prepare-dom-elements-for-bottom-pane\">Prepare DOM elements for bottom pane<\/h4>\n<p>  <\/p>\n<pre><code class=\"html\">&lt;ion-content> ... &lt;ion-drawer>   &lt;!-- First step -->   &lt;div class=\"first-step\">     &lt;div class=\"drinks\">       &lt;div class=\"drink\">         &lt;img src=\"https:\/\/raw.githubusercontent.com\/roman-rr\/cupertino-pane\/master\/playground\/img\/cup-1.png\" \/>         &lt;div class=\"size-drink\">M&lt;\/div>         &lt;div class=\"bg\">&lt;\/div>       &lt;\/div>       &lt;div class=\"drink\">         &lt;img src=\"https:\/\/raw.githubusercontent.com\/roman-rr\/cupertino-pane\/master\/playground\/img\/cup-2.png\" \/>         &lt;div class=\"size-drink\">L&lt;\/div>         &lt;div class=\"bg\">&lt;\/div>       &lt;\/div>     &lt;\/div>     &lt;div class=\"price\">       \u00a3        &lt;div class=\"big\">3&lt;\/div>       .45     &lt;\/div>   &lt;\/div>   &lt;!-- My Bag -->   &lt;div class=\"my-bag\">     &lt;h2>My Bag&lt;\/h2>     &lt;div class=\"list\">       &lt;!-- Item 1 -->       &lt;div class=\"item\">         &lt;div class=\"left-side\">           &lt;div class=\"drink\">             &lt;img src=\"https:\/\/raw.githubusercontent.com\/roman-rr\/cupertino-pane\/master\/playground\/img\/cup-1.png\" \/>             &lt;div class=\"bg\">&lt;\/div>           &lt;\/div>           &lt;div class=\"desc\">             &lt;div class=\"name\">Caramel Frappuccino&lt;\/div>             &lt;div class=\"size\">Size M&lt;\/div>             &lt;div class=\"price\">\u00a3 4.85&lt;\/div>           &lt;\/div>         &lt;\/div>         &lt;div class=\"amount\">x 1&lt;\/div>       &lt;\/div>       &lt;!-- Item 2 -->       &lt;div class=\"item\">         &lt;div class=\"left-side\">           &lt;div class=\"drink\">             &lt;img src=\"https:\/\/raw.githubusercontent.com\/roman-rr\/cupertino-pane\/master\/playground\/img\/cup-2.png\" \/>             &lt;div class=\"bg\">&lt;\/div>           &lt;\/div>           &lt;div class=\"desc\">             &lt;div class=\"name\">Mocha Frappuccino&lt;\/div>             &lt;div class=\"size\">Size L&lt;\/div>             &lt;div class=\"price\">\u00a3 3.70&lt;\/div>           &lt;\/div>         &lt;\/div>         &lt;div class=\"amount\">x 1&lt;\/div>       &lt;\/div>     &lt;\/div>     &lt;div class=\"footer\">       &lt;div class=\"line\">         &lt;div class=\"text\">           Total         &lt;\/div>         &lt;div class=\"amount\">           \u00a3 &lt;span id=\"total-amount\">&lt;\/span>.70         &lt;\/div>       &lt;\/div>       &lt;ion-button expand=\"block\">         Confirm Order       &lt;\/ion-button>     &lt;\/div>   &lt;\/div> &lt;\/ion-drawer> &lt;\/ion-content><\/code><\/pre>\n<p>  <\/p>\n<h4 id=\"apply-a-new-styles-for-bottom-pane\">Apply a new styles for bottom pane<\/h4>\n<p>  <\/p>\n<pre><code class=\"css\">.pane ion-drawer {   background: rgb(0, 112, 74) !important;   border-radius: 0 !important;   box-shadow: none !important; }  ion-drawer .first-step {   display: flex;   justify-content: space-between;   align-items: center;   margin-left: 20px;   margin-right: 20px;   transition: all 150ms ease-in-out;   opacity: 1; }  ion-drawer .first-step .price {   display: flex;   align-items: center;   font-size: 26px;   font-weight: 600;   color: #ffffff; }  ion-drawer .first-step .drinks {   display: flex;   justify-content: center;   align-items: center; }  .first-step .drinks .drink {   width: 48px;   height: 48px;   border-radius: 3px;   margin-right: 7px;   position: relative; }  .first-step .drinks .bg {   position: absolute;   width: 40px;   height: 40px;   border-radius: 50%;   background: rgb(30, 74, 52);   bottom: 0;   margin-left: auto;   margin-right: auto;   left: 0;   right: 0; }  .first-step .drinks .size-drink {   position: absolute;   width: 18px;   height: 18px;   border-radius: 50%;   background: #ffffff;   font-weight: 700;   right: -3px;   z-index: 1;   display: flex;   align-items: center;   justify-content: center;   font-size: 11px; }  .first-step .drinks img {   display: block;   position: absolute;   z-index: 2;   left: 0;   right: 0;   margin-left: auto;   margin-right: auto;   bottom: 6px; }<\/code><\/pre>\n<p>  <\/p>\n<h4 id=\"my-bag-state-styles\">My Bag state styles<\/h4>\n<p>  <\/p>\n<p>These styles also should be added in your <code>&lt;styles><\/code> block which will make My Bag container looks in order.<\/p>\n<p>  <\/p>\n<pre><code class=\"css\">ion-drawer .my-bag {   margin-left: 20px;   margin-right: 20px;   display: flex;   flex-direction: column;   align-items: center;   opacity: 0;   transition: all 150ms ease-in-out; }  ion-drawer .my-bag h2 {   font-weight: 800;   color: #ffffff;   margin-top: -60px;   font-size: 28px;   will-change: transform, opacity;   transform: translate3d(0px, 60px, 0px);   transition: all 150ms ease-in-out; }  ion-drawer .my-bag .list {   width: 100%;   will-change: transform, opacity;   transform: translate3d(0px, 60px, 0px);   transition: all 150ms ease-in-out; }  ion-drawer .my-bag .item {   display: flex;   justify-content: space-between;   margin-top: 25px; }  ion-drawer .my-bag .left-side {   display: flex;   align-items: center; }  ion-drawer .my-bag .drink {   width: 48px;   height: 48px;   border-radius: 3px;   margin-right: 20px;   position: relative;   transform: scale(1.2); }  .my-bag .drink .bg {   position: absolute;   width: 40px;   height: 40px;   border-radius: 50%;   background: rgb(30, 74, 52);   bottom: 0;   margin-left: auto;   margin-right: auto;   left: 0;   right: 0; }  .my-bag .drink img {   display: block;   position: absolute;   z-index: 2;   left: 0;   right: 0;   margin-left: auto;   margin-right: auto;   bottom: 6px; }  .my-bag .item .amount {   font-size: 22px;   font-weight: 700;   color: #ffffff;   display: flex;   align-items: center; }  .my-bag .item .desc .name {   color: #fff;   font-weight: 600;   font-size: 17px; }  .my-bag .item .desc .size {   color: #fff;   font-size: 14px;   margin-top: 2px; }  .my-bag .item .desc .price {   color: #88afa2;   font-size: 16px;   margin-top: 10px; }  .my-bag .footer {   border-top: 1px solid #ffffff2b;   position: absolute;   width: calc(100% - 40px);   bottom: 0;   padding-bottom: 35px;   background: #00704a; }  .my-bag .footer .line {   display: flex;   justify-content: space-between;   align-items: center;   margin-top: 20px;   margin-bottom: 20px; }  .my-bag .footer .line .text, .my-bag .footer .line .amount {   font-weight: 700;   color: #ffffff;   font-size: 26px; }  .my-bag .footer ion-button {   --border-radius: 30px;   font-weight: 700;   --background: #fff;   color: #00704a;   font-size: 17px;   letter-spacing: 0.1px; }  .my-bag .footer ion-button:active {   --background: #effffa; }<\/code><\/pre>\n<p>  <\/p>\n<h4 id=\"finalize-scripts\">Finalize scripts<\/h4>\n<p>  <\/p>\n<p>And Finalize JavaScript part which will execute Cupertino Pane library, present pane, handle add to Bag Button, some transitions and Pane behavior. <\/p>\n<p>  <\/p>\n<pre><code class=\"javascript\">&lt;script> const translateYRegex = \/\\.*translateY\\((.*)px\\)\/i; let paneY; let paneEl; let totalprice = 0; let itemprice = 3; let size = 'S'; const contentEl = document.querySelector('.content'); const firstStep = document.querySelector('.first-step'); const myBag = document.querySelector('.my-bag'); const myBagH2 = document.querySelector('.my-bag h2'); const myBagList = document.querySelector('.my-bag .list');  const firstHeight = 120; firstStep.style.height = `${firstHeight - 30}px`; contentEl.style.marginTop = `-${firstHeight + firstHeight\/2}px`; contentEl.style.paddingTop = `${firstHeight\/2}px`; contentEl.style.transform = `translateY(${firstHeight}px) translateZ(0px)`; contentEl.style.height = `calc(100% + ${firstHeight\/2}px + 30px)`;  function checkTransformations() {   paneEl = document.querySelector('.pane');   if (!paneEl) return;   paneY = parseFloat(translateYRegex.exec(paneEl.style.transform)[1]);    if (window.innerHeight - paneY - 30 > firstHeight) {     myBagH2.style.transform = 'translate3d(0px, 0px, 0px)';     myBagList.style.transform = 'translate3d(0px, 0px, 0px)';     myBag.style.opacity = 1;     firstStep.style.opacity = 0;   } else {     myBagH2.style.transform = 'translate3d(0px, 60px, 0px)';     myBagList.style.transform = 'translate3d(0px, 60px, 0px)';     myBag.style.opacity = 0;     firstStep.style.opacity = 1;   } }  let drawer = new CupertinoPane('ion-drawer', {   followerElement: '.content',   breaks: {     middle: {       enabled: true,       height: firstHeight     },     bottom: {       enabled: true,       height: 20     }   },   buttonClose: false,   showDraggable: false,   bottomClose: true,   draggableOver: true,   lowerThanBottom: false,   dragBy: ['.cupertino-pane-wrapper .pane', '.content'],   onDrag: () => checkTransformations(),   onTransitionEnd: () => checkTransformations() });  function presentPane(e) {   drawer.present({     animate: true   });    \/\/ Total price   totalprice += itemprice;   document.getElementsByClassName('big')[1].innerHTML = totalprice;   document.getElementById('total-amount').innerHTML = totalprice;   document.getElementsByClassName('size-drink')[1].innerHTML = size;    \/\/ Button animation   let icon = document.querySelector('#button-add ion-icon');   let text = document.querySelector('#button-add .button-text');   text.style.opacity = 0;    setTimeout(() => {     icon.style.opacity = 1;     text.innerHTML = 'Add 1 more'   }, 200);    setTimeout(() => {     icon.style.opacity = 0;   }, 1000);    setTimeout(() => {     text.style.opacity = 1;   }, 1300); }  function setActive(e, n, kfc, s) {   itemprice = n;   size = s;   let frame = document.querySelector('.active-frame ');   frame.style.transform = `translate3d(${55 * kfc}px, 0px, 0px)`;    let elems = document.getElementsByClassName('size');   for (var i = 0; i &lt; elems.length; i++) {     elems[i].classList.remove('active');   }   e.classList.add('active');   document.getElementsByClassName('big')[0].innerHTML = itemprice; } &lt;\/script><\/code><\/pre>\n<p>  <\/p>\n<h3 id=\"conclusions\">Conclusions<\/h3>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/github.com\/roman-rr\/cupertino-pane\/blob\/master\/docs\/images\/starbucks.gif?raw=true\" alt=\"starbucks\"\/><br \/>  <a href=\"https:\/\/output.jsbin.com\/jayicip\">Live demo results<\/a><br \/>  <a href=\"https:\/\/jsbin.com\/jayicip\/edit?html\">Code sources results<\/a><\/p>\n<p>  <\/p>\n<h3 id=\"thanks\">Thanks<\/h3>\n<p>  <\/p>\n<p><a href=\"https:\/\/dribbble.com\/shots\/6372790-Coffee-Ordering-Animation-Starbucks\">Dribble project<\/a><br \/>  <a href=\"https:\/\/medium.com\/@riz_maulana\/dribbble-challenge-coffee-ordering-animation-cf3ae17785fe\">Android version<\/a><\/p>\n<\/div>\n<\/div>\n<\/div>\n<p><!----><!----><\/div>\n<p><!----><!----><br \/> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/articles\/506862\/\"> https:\/\/habr.com\/ru\/articles\/506862\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-1\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<h4 id=\"tutorial-level-beginnerjunior\">Tutorial level: Beginner\/Junior<\/h4>\n<p>  <\/p>\n<h3 id=\"motivation\">Motivation<\/h3>\n<p>  <\/p>\n<p>Sometimes, when we surf dribbble, uplabs and similar design clouds, we often find many concepts or prototypes with animations, micro interactions, application flow and so on.<br \/>  I often find illustrations of mobile apps that are good and interesting, but of course they are still in the form of concept, so therefore, why don&#8217;t we try to apply them as an interface for applications that we will build next.<\/p>\n<p>  <\/p>\n<h3 id=\"original-concept\">Original concept<\/h3>\n<p>  <\/p>\n<p>In the Dribbble Challenge we will try to build an interface for <a href=\"https:\/\/dribbble.com\/shots\/6372790-Coffee-Ordering-Animation-Starbucks\">Coffee Ordering<\/a>, as I found on Dribble.<\/p>\n<p>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/pb\/t8\/nc\/pbt8ncbyhpo9hbwn3ecgeh32zyy.png\" data-src=\"https:\/\/habrastorage.org\/webt\/pb\/t8\/nc\/pbt8ncbyhpo9hbwn3ecgeh32zyy.png\"\/>  <\/p>\n<p><a href=\"https:\/\/dev-to-uploads.s3.amazonaws.com\/i\/autk6139mcjra1ic0s8w.gif\"><em>GIF here<\/em><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-402437","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/402437","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=402437"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/402437\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=402437"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=402437"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=402437"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}