I Built a Simple Top Loading Bar for Svelte 5
A small loading indicator can make navigation feel much more responsive. But when I looked for a top loading bar for my Svelte 5 app, I wanted something that was simple to add, worked with regular links, and didnβt make
A small loading indicator can make navigation feel much more responsive. But when I looked for a top loading bar for my Svelte 5 app, I wanted something that was simple to add, worked with regular links, and didnβt make SvelteKit-specific code mandatory.
So I built svelte-topbar: a Svelte component powered by NProgress, with automatic tracking for eligible same-origin links and an optional adapter for SvelteKit navigation.
Add it to a Svelte app
Install it with your package manager:
npm install svelte-topbar
You can also use Bun, pnpm, or Yarn. NProgress is installed automatically as a dependency, so you donβt need to add it separately.
Then render the component once near the top of your app:
<script>
import TopLoader from 'svelte-topbar';
</script>
<TopLoader color="#635bff" showSpinner={false} />
Same-origin links are tracked by default. The color and spinner are configurable, along with other NProgress options. The component is also compatible with SSR.
Use it for async work
Sometimes the loading state isnβt caused by a link. For example, you might want to show progress while a user-triggered operation is running. createTopLoader() gives you controls for that:
<script lang="ts">
import { createTopLoader } from 'svelte-topbar';
const loader = createTopLoader();
async function loadData() {
loader.start();
try {
await doWork();
} finally {
loader.done();
}
}
</script>
<button onclick={loadData}>Load data</button>
The returned controller also has methods such as setProgress, inc, and remove. It controls the shared NProgress instance, so render one <TopLoader /> component to configure that instance.
And if youβre using SvelteKit?
SvelteKit has its own navigation lifecycle callbacks, so the package includes an optional adapter for them. In your root +layout.svelte, set up the adapter and turn off the componentβs built-in link tracking:
<script lang="ts">
import TopLoader from 'svelte-topbar';
import { trackSvelteKitNavigation } from 'svelte-topbar/sveltekit';
trackSvelteKitNavigation();
</script>
<TopLoader trackLinks={false} />
<slot />
The adapter uses SvelteKitβs beforeNavigate and afterNavigate callbacks. Itβs a separate import, which means regular Svelte apps donβt need to depend on or import the SvelteKit adapter.
Why I made it
I wanted the basic case to stay basic: install the package, render one component, and get a useful loading indicator for normal same-origin links. When an app needs more control, thereβs an imperative API. And when itβs a SvelteKit app, the navigation integration is available without being required by every other Svelte app.
The package is new, so Iβd appreciate feedback from people who try itβespecially if the setup is unclear or you run into an issue in a real app.
Originally published by Dev.to WebDev. Aggregated on AIWithGhost for educational purposes β full credit and traffic to the original publisher.