Created
July 14, 2026 23:41
-
-
Save maiah/841d7dc651894d4b47b4b587be5f2806 to your computer and use it in GitHub Desktop.
Astro Top Bar Loader
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| --- | |
| // src/components/ProgressBar.astro | |
| --- | |
| <div id="top-progress-bar"></div> | |
| <style is:global> | |
| #top-progress-bar { | |
| position: fixed; | |
| top: 0; | |
| left: 0; | |
| width: 0%; | |
| height: 3px; | |
| background-color: #ff0000; /* YouTube Red - change to your brand color */ | |
| z-index: 9999; | |
| pointer-events: none; /* Ensure it doesn't block clicks */ | |
| opacity: 0; | |
| transition: width 0.2s ease, opacity 0.3s ease; | |
| } | |
| </style> | |
| <script> | |
| let progressInterval: number | ReturnType<typeof setInterval>; | |
| // Start the loading bar when navigation begins | |
| document.addEventListener('astro:before-preparation', () => { | |
| const progressBar = document.getElementById('top-progress-bar'); | |
| if (!progressBar) return; | |
| // Reset state | |
| progressBar.style.transition = 'none'; | |
| progressBar.style.width = '0%'; | |
| progressBar.style.opacity = '1'; | |
| // Force DOM reflow so the transition applies on the next frame | |
| void progressBar.offsetWidth; | |
| progressBar.style.transition = 'width 0.4s ease, opacity 0.3s ease'; | |
| let width = 10; | |
| progressBar.style.width = `${width}%`; | |
| // Create the "trickle" effect by incrementally increasing width | |
| progressInterval = setInterval(() => { | |
| // Don't go past 90% until the page actually loads | |
| if (width >= 90) { | |
| clearInterval(progressInterval); | |
| } else { | |
| width += Math.random() * 5 + 2; | |
| progressBar.style.width = `${width}%`; | |
| } | |
| }, 300); | |
| }); | |
| // Finish and hide the loading bar when the new page is ready | |
| document.addEventListener('astro:page-load', () => { | |
| const progressBar = document.getElementById('top-progress-bar'); | |
| if (!progressBar) return; | |
| // Stop the trickling | |
| clearInterval(progressInterval); | |
| // Shoot to 100% | |
| progressBar.style.width = '100%'; | |
| // Wait for the 100% animation to finish, then fade out | |
| setTimeout(() => { | |
| progressBar.style.opacity = '0'; | |
| // Reset width after it's invisible so it's ready for next time | |
| setTimeout(() => { | |
| progressBar.style.width = '0%'; | |
| }, 300); | |
| }, 400); | |
| }); | |
| </script> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment