JSFiddle - React, Tailwind, and code Playground

HTML

<script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/client/seriallency.min.js"></script>
<p>
Click on users to queue a 2 seconds promise. Try to clic as fast you can :)
</p>
<div class="graph">
  <div class="user" id="user1">
    <div class="name">
      User 1
    </div>
  </div>
  <div class="user" id="user2">
    <div class="name">
      User 2
    </div>
  </div>
  <div class="user" id="user3">
    <div class="name">
      User 3
    </div>
  </div>
</div>
<h3>
Seriallency state:
</h3>
<div>
getQuantityProcessing(): <span id="getQuantityProcessing"></span>
</div>
<div>
getQueueSize(): <span id="getQueueSize"></span>
</div>
<div>
getQueueSize('user1'): <span id="getQueueSize_user1"></span>
</div>
<div>
getQueueSize('user2'): <span id="getQueueSize_user2"></span>
</div>
<div>
getQueueSize('user3'): <span id="getQueueSize_user3"></span>
</div>

CSS

.user {
  height: auto;
  border-top: 1px solid gray;
  user-select: none;
}

.user:last-child {
  border-bottom: 1px solid gray;
}

.user:after {
  display: table;
  content: '';
  clear: both;
}

.user .name {
  float: left;
  height: 20px;
  width: 60px;
  background-color: lightgray;
  padding: 10px 10px;
  cursor: pointer;
  text-align: center;
}
.user .name:hover{
  background-color: aliceblue;
}

.promise {
  width: 50px;
  height: 20px;
  float: left;
  margin-left: 5px;
  margin-top: 10px;
  text-align: center;
  position: relative;
  overflow: hidden;
}
.promise:before{
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  bottom: 0;
  width: 0%;
  background-color: lightgreen;
  opacity: .5;
}

.promise.pending {
  background-color: yellow;
}
.promise.pending:before{
  transition: width 2s linear;
  width: 100%;
}

.promise.done {
  background-color: lightgreen;
}

.promise.queued {
  background-color: lightblue;
}

JavaScript

var seriallency = new Seriallency();

var users = [
	{
    id: 'user1',
    processes: 0
  },
  {
    id: 'user2',
    processes: 0
  },
  {
    id: 'user3',
    processes: 0
  }
];
seriallency.on('resolved', refreshSeriallencyStatus);
refreshSeriallencyStatus();

$('.graph').on('click', '.user .name', function (event){
	var userId = $(this).closest('.user').attr('id');
  queueProcess(userId);
})

function queueProcess(userId){
	var counter;
	var user = users.find(function(user){ return user.id === userId; });
  user.processes += 1;
  createUserStep(user.id, user.processes, 'queued');
  setTimeout(function (){
  	// this timeout is only to allow css transition to start with loadbar empty
    seriallency.push({
      serializeBy: user.id,
      fn: someProcess,
      params:[user.id, user.processes]
    });
    refreshSeriallencyStatus();
  }, 1);
}

function someProcess(user, step){
	setUserStepStatus(user, step, 'pending');
  refreshSeriallencyStatus();
	return new Promise(function (resolve, reject){
    setTimeout(function (){
			setUserStepStatus(user, step, 'done');
      resolve();
    }, 2000);
  });
}

function createUserStep(user, step, initialStatus){
	var $promise = $('<div></div>', { 
  	id: user + '_step' + step, 
    class:'promise ' + initialStatus,
    text: 'p.' + step
  });
	$('#' + user).append($promise);
}

function setUserStepStatus(user, step, status){
	$('#' + user + '_step' + step).removeClass('pending done queued').addClass(status);
}

function refreshSeriallencyStatus(){	$('#getQuantityProcessing').text(seriallency.getQuantityProcessing());
  $('#getQueueSize').text(seriallency.getQueueSize());
  $('#getQueueSize_user1').text(seriallency.getQueueSize('user1'));
  $('#getQueueSize_user2').text(seriallency.getQueueSize('user2'));
  $('#getQueueSize_user3').text(seriallency.getQueueSize('user3'));
}