Skip to content

CI Build Status Chip

A copy-paste indicators component in pure HTML, CSS & vanilla JS. Zero dependencies, framework-agnostic, MIT-licensed.

IndicatorsHTMLJavaScriptCSSany framework
Queued

Copy into your project

HTML
<div class="nuda-in2-cistatus" data-state="queued" role="status" aria-live="polite">
  <span class="nuda-in2-cistatus__icon" aria-hidden="true">
    <svg class="nuda-in2-cistatus__i-queued" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
      <circle cx="12" cy="12" r="9" />
      <path d="M12 7v5l3 2" />
    </svg>
    <svg class="nuda-in2-cistatus__i-running" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round">
      <path d="M21 12a9 9 0 1 1-3-6.7" />
    </svg>
    <svg class="nuda-in2-cistatus__i-passed" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">
      <path d="M20 6 9 17l-5-5" />
    </svg>
  </span>
  <span class="nuda-in2-cistatus__text">Queued</span>
</div>
JavaScript
/* CI Build Status Chip — vanilla JS
   Advances queued -> running -> passed once, updating the
   visible label so the status is always stated in words. */

(function () {
  var STEPS = [
    { key: "queued", text: "Queued", hold: 1400 },
    { key: "running", text: "Running", hold: 2200 },
    { key: "passed", text: "Passed", hold: 4000 },
  ];

  document.querySelectorAll(".nuda-in2-cistatus").forEach(function (el) {
    var label = el.querySelector(".nuda-in2-cistatus__text");
    var i = 0;
    function advance() {
      var s = STEPS[i];
      el.setAttribute("data-state", s.key);
      label.textContent = s.text;
      if (i < STEPS.length - 1) {
        i++;
        setTimeout(advance, s.hold);
      }
    }
    setTimeout(advance, STEPS[0].hold);
  });
})();
CSS
.nuda-in2-cistatus {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 6px 12px;
  background: #161616;
  border: 1px solid rgba(255,255,255,.1);
  border-radius: 8px;
  font-size: 11px;
  font-weight: 600;
  color: #cfcfcf;
}

.nuda-in2-cistatus__icon {
  position: relative;
  width: 13px;
  height: 13px;
  flex: 0 0 auto;
}

.nuda-in2-cistatus__icon svg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: none;
}

.nuda-in2-cistatus[data-state="queued"] .nuda-in2-cistatus__i-queued {
  display: block;
  color: #a0a0a0;
}

.nuda-in2-cistatus[data-state="running"] .nuda-in2-cistatus__i-running {
  display: block;
  color: #e4ff54;
  animation: _nuda-in2cistatus-spin .9s linear infinite;
}

.nuda-in2-cistatus[data-state="passed"] .nuda-in2-cistatus__i-passed {
  display: block;
  color: #6ee7b7;
}

.nuda-in2-cistatus[data-state="running"] .nuda-in2-cistatus__text {
  color: #e4ff54;
}

.nuda-in2-cistatus[data-state="passed"] .nuda-in2-cistatus__text {
  color: #6ee7b7;
}

@keyframes _nuda-in2cistatus-spin {
  to {
    transform: rotate(360deg);
  }
}

@media (prefers-reduced-motion:reduce) {
  .nuda-in2-cistatus__i-running {
    animation: none !important;
  }
}

How to use CI Build Status Chip

Paste the HTML where you need it and the CSS into a global stylesheet (or a <style> tag). Every class is prefixed nuda- so it never collides with Tailwind or your own styles. Tweak the CSS custom properties to match your design system.

Works in React, Vue, Svelte, Astro, Next.js, Nuxt, Laravel Blade, Django, Rails — or a single .html file. No npm install, no build step.

More indicators components

← Browse all NudaUI components