- 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
72 lines
2.8 KiB
Plaintext
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>
|