JSFiddle - React, Tailwind, and code Playground

by Edbert

HTML

<div class='card'>
  <div class='product'>
    
  </div>
  <div class='price-tag-wrapper'>
    <div class='price-tag'>
      <span class='price'>$19.99</span>
      <div class='purchase-qty' onclick='setQuantity(this, event)'>
        <span class='placeholder-only'>0</span>
        <span class='icon'>icon</span>
        <div class='btn btn-decrease'>-</div>      
        <input type='number' class='input' value='0' disabled />
        <div class='btn btn-increase'>+</div>
      </div>      
    </div>
  </div>  
</div>

<div class='card'>
  <div class='product'>
    
  </div>
  <div class='price-tag-wrapper'>
    <div class='price-tag'>
      <span class='price'>$39.99</span>
      <div class='purchase-qty' onclick='setQuantity(this, event)'>
        <span class='placeholder-only'>0</span>
        <span class='icon'>icon</span>
        <div class='btn btn-decrease'>-</div>      
        <input type='number' class='input' value='0' disabled />
        <div class='btn btn-increase'>+</div>
      </div>      
    </div>
  </div>  
</div>

CSS

.card {
  position: relative;
  border: 1px solid #666;
}

.card .product {
  width: 300px;
  height: 200px;
  position: relative;
  background-image: url('https://open3dmodel.com/wp-content/uploads/2020/03/Books-3D-Model.jpg');
  background-repeat: repeat;
}

.card .price-tag-wrapper {
  position: absolute;
  bottom: 0;
  left: 0;
  right: 0;
  line-height: 2.5em;
  background: rgba(100,100,100,0.75);
  color: #fff;
}

.card .price-tag {
  float: right;
  padding: 0.5em 1em;
}

.card .price {
  display: inline-block;
}

.card .purchase-qty {
  position: relative;
  background: darkgreen;
  width: 3em;
  text-align: center;
  display: inline-block;
  transition: width ease-in-out 1s;
}

.card .purchase-qty.open {
  width: 9em;
}

.card .purchase-qty .icon {
  z-index: 10;
}

.card .purchase-qty.open .icon {
  z-index: inherit;
}

.card .purchase-qty .icon, .card .purchase-qty .btn, .card .purchase-qty .input {
  position: absolute;
  top: 0;
  bottom: 0;
  right: 0;
  width: 3em;
  transition: transform ease-in-out 1s;
  background: darkgreen;
}

.card .purchase-qty .input {
  background: white;
  color: #000;
  text-align: center;
}

.card .purchase-qty.open .input {
  transform: translateX(-100%);
}

.card .purchase-qty.open .btn.btn-decrease {
  transform: translateX(-200%);
}

/* Chrome, Safari, Edge, Opera */
input::-webkit-outer-spin-button,
input::-webkit-inner-spin-button {
  -webkit-appearance: none;
  margin: 0;
}

/* Firefox */
input[type=number] {
  -moz-appearance: textfield;
}

JavaScript

var autoClose;
var autoCloseDuration = 3000;	// set this for timeoute duration

function setQuantity(s, e) {
	elem = e;
  sender = s;
  var inputElement;
  
  clearTimeout(autoClose);
  
  Array.from(document.querySelectorAll('.purchase-qty.open')).forEach(function(el) {
  	if (s != el) {
    	setIconValue(el);
    }
	});
  
  if (!s.classList.contains('open')) {
		s.classList.add('open');
  }
  else {
  	inputElement = s.getElementsByClassName('input')[0];
    if (e.target.textContent == '+') {      
      inputElement.value = inputElement.valueAsNumber + 1;
    }
    else if (e.target.textContent == '-') {
      inputElement.value = inputElement.valueAsNumber - 1;
    }
    
    s.setAttribute('data-qty', inputElement.value);
  }
  
  autoClose = setTimeout(function() { setIconValue(s); }, autoCloseDuration);
  
}

function setIconValue(s) {
	if (s.getAttribute('data-qty') != null) {
		s.getElementsByClassName('icon')[0].innerText = s.getAttribute('data-qty');
  }
  s.classList.remove('open');
}