nicholai-work-2026/src/components/ReadingProgress.astro
Nicholai 2ca66ccc6d Update theme variable usage and add ThemeToggle component
- Refactor component styles to use CSS custom properties for colors and backgrounds.
- Replace hard‑coded Tailwind classes with theme variables across BlogCard, BlogFilters, Footer, GridOverlay, Navigation, PostNavigation, ReadingProgress, RelatedPosts, TableOfContents, ThemeToggle, sections, layouts, pages, and global.css.
- Add ThemeToggle component for user‑controlled theme switching.
- Update global styles to define new theme variables.
- Ensure all components respect theme changes and maintain accessibility.

Hubert The Eunuch
2025-12-18 17:08:52 -07:00

72 lines
2.8 KiB
Plaintext

---
// Reading progress bar that tracks scroll position
---
<div id="reading-progress-container" class="fixed top-0 left-0 w-full h-[3px] z-[100] bg-[var(--theme-bg-primary)]/50">
<div id="reading-progress-bar" class="h-full bg-brand-accent w-0 transition-[width] duration-100 ease-out shadow-[0_0_10px_rgba(221,65,50,0.5)]"></div>
</div>
<div id="reading-status" class="fixed top-4 right-4 z-[90] hidden lg:flex items-center gap-3 px-3 py-1 bg-[var(--theme-overlay)] backdrop-blur-md border border-[var(--theme-border-primary)] opacity-0 transition-opacity duration-300 pointer-events-none">
<div class="w-1.5 h-1.5 bg-brand-accent rounded-full animate-pulse"></div>
<span class="text-[9px] font-mono text-[var(--theme-text-secondary)] uppercase tracking-widest">READING_BUFFER: <span id="progress-text" class="text-[var(--theme-text-primary)]">0%</span></span>
</div>
<script>
function initReadingProgress() {
const progressBar = document.getElementById('reading-progress-bar');
const statusContainer = document.getElementById('reading-status');
const statusText = document.getElementById('progress-text');
if (!progressBar) return;
function updateProgress() {
const article = document.querySelector('article');
if (!article) return;
const articleRect = article.getBoundingClientRect();
const articleTop = window.scrollY + articleRect.top;
const articleHeight = article.offsetHeight;
const windowHeight = window.innerHeight;
const scrollY = window.scrollY;
// Calculate progress based on article position
const start = articleTop;
const end = articleTop + articleHeight - windowHeight;
const current = scrollY;
let progress = 0;
if (current >= start && current <= end) {
progress = ((current - start) / (end - start)) * 100;
} else if (current > end) {
progress = 100;
}
const percentage = Math.round(Math.min(100, Math.max(0, progress)));
progressBar.style.width = `${percentage}%`;
if (statusText) {
statusText.textContent = `${percentage}%`;
}
// Show status only when reading (between 1% and 99%)
if (statusContainer) {
if (percentage > 2 && percentage < 98) {
statusContainer.classList.remove('opacity-0');
} else {
statusContainer.classList.add('opacity-0');
}
}
}
window.addEventListener('scroll', updateProgress, { passive: true });
window.addEventListener('resize', updateProgress, { passive: true });
updateProgress();
}
// Initialize on page load
initReadingProgress();
// Re-initialize on Astro page transitions
document.addEventListener('astro:page-load', initReadingProgress);
</script>