demo · v149
Scroll Progress Tracker
Programmatic scrollTo() returns a Promise that resolves with { interrupted: false } on completion or { interrupted: true } if another scroll interrupts it. Chain each chapter scroll sequentially using await — the progress bar only advances when each scroll actually lands, not on a timer.
Click Start tour to scroll through all five chapters automatically. Interrupt at any time — the Promise resolves with
{ interrupted: true } and the progress bar pauses. Resume to continue from the interrupted chapter. Click any chapter in the chapter strip to jump directly.
Speed:
Current chapter—
Completed0
Interruptions0
Status—
Click "Start tour" to begin the promise-driven scroll sequence.
// Promise-chained chapter scroll with progress tracking
async function runTour(chapters, scroller) {
for (let i = 0; i < chapters.length; i++) {
const chapter = chapters[i];
const targetY = chapter.offsetTop;
updateProgress(i, 'scrolling');
const result = await scroller.scrollTo({
top: targetY,
behavior: 'smooth',
});
if (result.interrupted) {
// User scrolled away — pause here and wait for resume
log('Chapter ' + (i+1) + ' interrupted — awaiting resume…');
await waitForResume(); // user clicks Resume button
i--; // retry the interrupted chapter
continue;
}
updateProgress(i + 1, 'reached');
log('Chapter ' + (i+1) + ' ✓ — promise resolved { interrupted: false }');
}
}
// Without promises, you'd need setTimeout guesses or IntersectionObserver
// to know if a programmatic scroll "landed". The promise makes it precise.