Slide to Confirm
Drag the knob across the track to commit an action. It snaps back if you let go early and locks green when confirmed.
Preview and code
index.html
<div class="sc"><span class="sc__l">Slide to confirm</span><button class="sc__k" type="button" aria-label="Slide to confirm"><svg class="sc__a" viewBox="0 0 24 24" aria-hidden="true"><path d="M5 12h14M13 6l6 6-6 6"/></svg><svg class="sc__c" viewBox="0 0 24 24" aria-hidden="true"><path d="m5 12 5 5 9-10"/></svg></button></div>
styles.css
.sc{position:relative;width:270px;height:54px;border-radius:999px;background:#f1f1f2;border:1px solid #e4e4e7;box-shadow:inset 0 2px 4px rgba(0,0,0,.06);transition:background-color .3s ease,border-color .3s ease;overflow:hidden}
.sc__l{position:absolute;inset:0;display:grid;place-items:center;padding-left:40px;color:#737373;font:500 15px/1 system-ui,sans-serif;pointer-events:none;transition:color .3s ease}
.sc__k{position:absolute;left:4px;top:4px;display:grid;place-items:center;width:44px;height:44px;padding:0;border:0;border-radius:50%;background:#fff;color:#262626;box-shadow:0 2px 6px rgba(0,0,0,.2);cursor:grab;touch-action:none;transition:transform .28s cubic-bezier(.3,1.2,.5,1)}
.sc.is-drag .sc__k{transition:none;cursor:grabbing}
.sc svg{grid-area:1/1;width:18px;height:18px;fill:none;stroke:currentColor;stroke-width:2;stroke-linecap:round;stroke-linejoin:round}
.sc__c{display:none}
.sc.is-done{background:#10b981;border-color:#0e9f6e}
.sc.is-done .sc__l{color:#fff;padding-left:0}
.sc.is-done .sc__a{display:none}
.sc.is-done .sc__c{display:block;color:#059669}
.sc__k:focus-visible{outline:2px solid #1659f5;outline-offset:2px}
@media (prefers-reduced-motion:reduce){.sc__k{transition:none}}
script.js
const t=document.querySelector('.sc'),k=t.querySelector('.sc__k'),l=t.querySelector('.sc__l');let x=0,drag=false,sx=0,done=false;
const max=()=>t.clientWidth-k.offsetWidth-10;
function fin(){done=true;x=max();k.style.transform='translateX('+x+'px)';t.classList.add('is-done');l.textContent='Confirmed';l.style.opacity=1;setTimeout(()=>{done=false;x=0;k.style.transform='';t.classList.remove('is-done');l.textContent='Slide to confirm'},2200)}
k.addEventListener('pointerdown',e=>{if(done)return;drag=true;sx=e.clientX-x;k.setPointerCapture(e.pointerId);t.classList.add('is-drag')});
k.addEventListener('pointermove',e=>{if(!drag)return;x=Math.max(0,Math.min(max(),e.clientX-sx));k.style.transform='translateX('+x+'px)';l.style.opacity=1-x/max()});
function end(){if(!drag)return;drag=false;t.classList.remove('is-drag');if(x>=max()*.92)fin();else{x=0;k.style.transform='';l.style.opacity=1}}
['pointerup','pointercancel'].forEach(e=>k.addEventListener(e,end));
k.addEventListener('keydown',e=>{if(e.key==='Enter'&&!done)fin()});
About
Good for irreversible or high-intent actions. Pointer events drive the drag, and pressing Enter on the knob confirms for keyboard users.