JSFiddle - React, Tailwind, and code Playground

by Vasil Svetoslavov

HTML

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.0/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.3.1/js/bootstrap.bundle.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.3.1/css/bootstrap.min.css">
<div class="container-fluid p-4">
  <button type="button" class="btn btn-primary btn-open-wizard" data-bs-toggle="modal" data-bs-target="#cardWizardModal" onclick="resetStep();">
    Open Wizard
  </button>

  <div class="form-check">
    <input class="form-check-input" type="checkbox" value="" id="optShowProgress" checked onclick="showProgress=this.checked;console.log(showProgress);">
    <label class="form-check-label" for="optShowProgress">
      Show progress
    </label>
  </div>

  <div class="modal modal-lg fade" id="cardWizardModal" tabindex="-1" aria-labelledby="cardWizardTitle" aria-hidden="true" data-bs-backdrop="static">
    <div class="modal-dialog modal-dialog-scrollable">
      <div class="modal-content">
        <div class="modal-header">
          <h3 class="modal-title" id="cardWizardTitle">Replace Card</h3>
          <div class="d-flex align-items-center">

            <div class="row" id="linkContainer">
            </div>

          </div>
        </div>
        <div class="modal-body">

          <!-- Step 1 -->
          <div class="step step-1" data-hint="Replacement Reason">

            <div class="alert alert-warning">
              WARNING! This card will be replaced with a <em>Swift Go To Hell</em> card
            </div>

            <div class="alert alert-danger bg-gradient">
              IMPORTANT! There are products on this card that can not be migrated
            </div>

            <div class="form-group">
              <label for="replacement-reason" class="text-primary">Replacement Reason</label>
              <select class="form-select btn btn-primary text-start" id="replacement-reason">
                <option>Faulty...

CSS

/*
.card-wizard {
  border: 1px solid #ccc;
  padding: 10px;
  border-radius: 5px;
  margin-top: 20px;
}
*/
:root {
  --bs-primary: #000 !important;
}

.product+.product {
  margin-top: 5px;
}

.hidden {
  display: none !important;
}

.product {
  border: 1px solid #ccc;
  border-radius: 5px;
  padding: 5px;
}

.product-title {
  font-weight: bold;
}


.toast-translucent {
  opacity: 0.9;
}

.toast-translucent:hover {
  opacity :1;
}

a.indicator-link {
	display: inline-block;
	opacity: .75;
	font-size: 10px;
	height: 20px;
	width: 20px;
	border-radius: 10px;
  text-align: center;
  color: white;
  text-decoration: none;
  padding-top: 2px;
  padding-left: 1px;
}

a.indicator-link:focus,
a.indicator-link:active,
a.indicator-link:hover,
a.indicator-link.active {
	opacity: 1;
}

.indicator.col {

}

JavaScript

var currentStep = 1;

var showProgress = true;

var tooltipsInitialized = false;

function isStepPresent(step) {
  var stepEl = $('.step.step-' + step);
  if (stepEl.length > 0) {
    return true;
  }
  return false;
}

function isFirstStep(step) {
  if (step == 1) {
    return true;
  }

  return false;
}

function isLastStep(step) {
  return !isStepPresent(step + 1);
}

function goToStep(step) {

  if (step == currentStep) {
    return;
  }
  if (!isStepPresent(step)) {
    return;
  }

  currentStep = step;

	$('.indicator-link').removeClass('active');
  $('.indicator-link').removeClass('bg-primary');
  $('.indicator-link').removeClass('bg-secondary');
  $('.indicator-link').addClass('bg-secondary');

  if (showProgress) {
    for (s = 1; s <= step; s++) {
      $('.indicator-link.link-step-' + s).removeClass('bg-secondary');
      $('.indicator-link.link-step-' + s).addClass('bg-primary');
    }
  } else {
    $('.indicator-link.link-step-' + step).removeClass('bg-secondary');
    $('.indicator-link.link-step-' + step).addClass('bg-primary');
  }
  
  $('.indicator-link.link-step-' + step).addClass('active');

  $('.btn-back').removeClass('hidden');
  $('.btn-next').removeClass('hidden');
  $('.btn-finish').removeClass('hidden');

  if (isFirstStep(step)) {
    $('.btn-back').addClass('hidden');
  }

  if (isLastStep(step)) {
    $('.btn-next').addClass('hidden');
  } else {
    $('.btn-finish').addClass('hidden');
  }

  $('.step').slideUp();
  //$('.step-' + step).removeClass('hidden');
  $('.step.step-' + step).slideDown();
}

function initTooltips() {
  /* if (tooltipsInitialized) {
    return;
  } */

  $('[data-bs-toggle="tooltip"]').each(function(idx, el) {
    new bootstrap.Tooltip(el);
  });

  tooltipsInitialized = true;
}

function resetStep() {
  currentStep = 1;
  $('#linkContainer').html(null);

  //create step links
  var s = 1;
  while (isStepPresent(s)) {
    var linkClass = s == 1 ? 'bg-primary' : 'bg-secondary';
    linkClass += s == 1 ? '...