reading_progress
Progress bar showing scroll position for long-form content.
See the blue bar at the very top of your browser? Scroll this page and watch it grow. That's this controller in action.
Usage
<!-- Place at the top of your layout -->
<div data-controller="reading-progress" class="reading-progress"></div>
Required CSS
.reading-progress {
position: fixed;
top: 0;
left: 0;
height: 3px;
background-color: theme('colors.blue.500');
z-index: 50;
width: 0%;
transition: width 0.1s ease-out;
}
Source
import { Controller } from "@hotwired/stimulus";
export default class extends Controller {
connect() {
this.boundUpdateProgress = this.updateProgress.bind(this);
window.addEventListener("scroll", this.boundUpdateProgress, {
passive: true
});
this.updateProgress();
}
disconnect() {
window.removeEventListener("scroll", this.boundUpdateProgress);
}
updateProgress() {
const scrollTop = window.scrollY;
const docHeight = document.documentElement.scrollHeight - window.innerHeight;
const progress = docHeight > 0 ? (scrollTop / docHeight) * 100 : 0;
this.element.style.width = `${Math.min(100, Math.max(0, progress))}%`;
}
}
Features
- Uses passive scroll listener for performance
- Smooth width transitions
- Clamps progress between 0-100%
- Properly cleans up on disconnect
Customization
Adjust the appearance via CSS:
.reading-progress {
height: 4px; /* Thicker bar */
background: linear-gradient( /* Gradient */
to right,
theme('colors.blue.500'),
theme('colors.purple.500')
);
}