Skip to content
Navigation Fancy Stable

ScrollProgress

.md

Thin reading-progress bar that fills as the page — or a target element — scrolls, driven by a zero-JS CSS scroll-timeline where supported and a throttled scroll listener everywhere else, with an optional accessible progressbar label

Available for Svelte 5, React, and Vue 3.

Preview

Installation

pnpm add fancy-ui-svelte
import { ScrollProgress } from "fancy-ui-svelte";

Usage

svelte
<script lang="ts">
	import { ScrollProgress } from "fancy-ui-svelte";

	let box = $state<HTMLElement | null>(null);
</script>

<div class="mx-auto flex w-full max-w-sm flex-col gap-2 p-6">
	<ScrollProgress target={box} position="inline" class="text-primary rounded-full" />
	<div
		bind:this={box}
		class="border-border bg-card h-56 overflow-y-auto rounded-lg border p-4 text-sm leading-relaxed"
	>
		<p class="text-foreground text-xs font-semibold tracking-wide uppercase">0.9.0</p>
		<p class="text-muted-foreground mt-1 mb-4">
			Redesigned the sidebar navigation and shipped a set of layout primitives for scroll-driven
			pages.
		</p>
		<p class="text-foreground text-xs font-semibold tracking-wide uppercase">0.8.0</p>
		<p class="text-muted-foreground mt-1 mb-4">
			Added dark-mode tokens to every core component and fixed a focus-trap bug in the command menu.
		</p>
		<p class="text-foreground text-xs font-semibold tracking-wide uppercase">0.7.0</p>
		<p class="text-muted-foreground mt-1 mb-4">
			Introduced the shared motion foundation: easing tokens, a reduced-motion rune, and staggered
			reveal presets.
		</p>
		<p class="text-foreground text-xs font-semibold tracking-wide uppercase">0.6.0</p>
		<p class="text-muted-foreground mt-1">
			Rebuilt the docs search and added keyboard shortcuts for jumping between components.
		</p>
	</div>
	<p class="text-muted-foreground text-xs">
		Scroll the panel above — the bar tracks that element directly (<code class="text-xs"
			>target</code
		>), not the whole page.
	</p>
</div>

Examples

Basic Usage

Labelled

Accessible role="progressbar" with a live percentage readout.

Props

PropTypeDefaultDescription
target HTMLElement | nullnullAn element to track instead of the document. Forces JS mode — reactively, so a target that only becomes available after mount is still picked up correctly.
position "top" | "bottom" | "inline""top""top"/"bottom" pin the bar to that viewport edge (position: fixed); "inline" renders it in normal flow.
label string-Announces the bar as role="progressbar" with this accessible name. Forces JS mode; omitted, the bar is aria-hidden.
class string-Additional CSS classes
ref HTMLDivElement | nullnullBindable reference to the root element