.ctc-drag { display: flex; gap: 8px; list-style: none; margin: 0; padding: 0; }
.ctc-drag-chip { display: inline-flex; align-items: center; padding: 8px 16px; background: #1f1f2e; color: #c4b5fd; border: 1px solid rgba(124,108,255,0.35); border-radius: 999px; font: 600 12px/1 system-ui, sans-serif; cursor: grab; user-select: none; touch-action: none; transition: transform 0.18s ease, background 0.2s; }
.ctc-drag-chip:hover { background: rgba(124,108,255,0.18); }
.ctc-drag-chip.is-dragging { cursor: grabbing; background: #7c6cff; color: #fff; z-index: 2; transition: none; }
.ctc-drag-chip:focus-visible { outline: 2px solid #a78bfa; outline-offset: 2px; } <ul class="ctc-drag" role="listbox" aria-label="Reorder tags">
<li class="ctc-drag-chip" tabindex="0" data-ctc-drag>Frontend</li>
<li class="ctc-drag-chip" tabindex="0" data-ctc-drag>Backend</li>
<li class="ctc-drag-chip" tabindex="0" data-ctc-drag>DevOps</li>
</ul>
(function () {
document.querySelectorAll('.ctc-drag').forEach(function (list) {
var dragged = null;
list.querySelectorAll('[data-ctc-drag]').forEach(function (chip) {
chip.addEventListener('pointerdown', function (e) {
dragged = chip;
chip.classList.add('is-dragging');
chip.setPointerCapture(e.pointerId);
});
chip.addEventListener('pointermove', function (e) {
if (dragged !== chip) return;
var siblings = Array.from(list.children).filter(function (c) { return c !== chip; });
for (var i = 0; i < siblings.length; i++) {
var rect = siblings[i].getBoundingClientRect();
if (e.clientX > rect.left && e.clientX < rect.right) {
var dragRect = chip.getBoundingClientRect();
if (e.clientX < rect.left + rect.width / 2) {
list.insertBefore(chip, siblings[i]);
} else {
list.insertBefore(chip, siblings[i].nextSibling);
}
break;
}
}
});
chip.addEventListener('pointerup', function () {
chip.classList.remove('is-dragging');
dragged = null;
});
chip.addEventListener('keydown', function (e) {
var siblings = Array.from(list.children);
var idx = siblings.indexOf(chip);
if (e.key === 'ArrowLeft' && idx > 0) {
e.preventDefault();
list.insertBefore(chip, siblings[idx - 1]);
chip.focus();
} else if (e.key === 'ArrowRight' && idx < siblings.length - 1) {
e.preventDefault();
list.insertBefore(chip, siblings[idx + 1].nextSibling);
chip.focus();
}
});
});
});
})(); Live preview Edit any tab — preview updates live Ready