DEV Community

Angga Islami
Angga Islami

Posted on

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 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
Enter fullscreen mode Exit fullscreen mode

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} />
Enter fullscreen mode Exit fullscreen mode

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>
Enter fullscreen mode Exit fullscreen mode

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 />
Enter fullscreen mode Exit fullscreen mode

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.

Top comments (0)