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');
}