JSFiddle - React, Tailwind, and code Playground

by oktaviardi pratama

HTML

<div class="pill-container">
    <input type="checkbox" id="tabToggle" class="pill-toggle-input">
    
    <div class="pill-labels">
      <label for="tabToggle" class="pill-label" aria-pressed="true">Ringkasan</label>
      <label for="tabToggle" class="pill-label" aria-pressed="false">Detail</label>
    </div>

    <div class="pill-indicator"></div>
  </div>

CSS

.pill-container {
      position: relative;
      display: inline-flex;
      width: 240px;
      height: 48px;
      background-color: #e5e7eb;
      border-radius: 9999px;
      overflow: hidden;
      font-family: system-ui, sans-serif;
    }

    /* Hidden checkbox */
    .pill-toggle-input {
      position: absolute;
      opacity: 0;
      pointer-events: none;
    }

    /* Label wrapper — covers full pill */
    .pill-labels {
      display: flex;
      width: 100%;
      height: 100%;
      z-index: 1;
    }

    .pill-label {
      flex: 1;
      display: flex;
      align-items: center;
      justify-content: center;
      padding: 0 1rem;
      cursor: pointer;
      color: #6b7280;
      transition: color 0.3s ease;
      user-select: none;
    }

    .pill-label:hover {
      color: #1d4ed8;
    }

    .pill-label.active {
      color: #1d4ed8;
      font-weight: 600;
    }

    /* The white sliding pill (indicator) */
    .pill-indicator {
      position: absolute;
      top: 4px;
      left: 4px;
      width: calc(50% - 8px);
      height: calc(100% - 8px);
      background: white;
      border-radius: 9999px;
      box-shadow: 0 4px 6px rgba(0, 0, 0, 0.05);
      transition: left 0.35s cubic-bezier(0.68, -0.55, 0.27, 1.55);
      z-index: 0;
    }

    /* When checkbox is checked → move indicator to right */
    .pill-toggle-input:checked ~ .pill-indicator {
      left: calc(50% + 4px); /* 50% + left padding (4px) */
    }

    /* Optional: focus outline */
    .pill-label:focus-visible {
      outline: 2px solid #3b82f6;
      outline-offset: 2px;
    }

    .pill-indicator {
  box-shadow: 
    0 4px 12px rgba(0,0,0,0.08),
    0 2px 4px rgba(0,0,0,0.04);
}
.pill-indicator:hover {
  box-shadow: 
    0 6px 16px rgba(0,0,0,0.12),
    0 3px 6px rgba(0,0,0,0.06);
}

JavaScript

const toggle = document.getElementById('tabToggle');
    const labels = document.querySelectorAll('.pill-label');

    toggle.addEventListener('change', () => {
      labels.forEach((lbl, i) => {
        lbl.setAttribute('aria-pressed', toggle.checked === (i === 1));
        lbl.classList.toggle('active', toggle.checked === (i === 1));
      });
    });

    // Initialize state
    labels[0].classList.add('active');
    labels[0].setAttribute('aria-pressed', 'true');
    labels[1].setAttribute('aria-pressed', 'false');