Page Progress
A thin top-of-page progress indicator for route transitions and optimistic navigation feedback. It pairs with the useProgressBar hook to animate route changes without blocking content.
Dark ModeAnimatedPortal
Install
$
npx react-principles add page-progress01
Live Demo
This demo wires the component to useProgressBar so you can replay a route transition and observe the bar animating at the top of the viewport.
Simulate a route transition
Trigger the hook and watch the top edge of the viewport for the animated progress bar.
Visible
No
Progress
0%
Runs
0
02
Code Snippet
src/ui/PageProgress.tsx
import { useState } from "react"; import { PageProgress } from "@/ui/PageProgress"; import { useProgressBar } from "@/shared/hooks/useProgressBar"; export function RouteFeedback() { const [navigationKey, setNavigationKey] = useState("initial"); const { progress, visible } = useProgressBar(navigationKey); return ( <> <button onClick={() => setNavigationKey(`nav-${Date.now()}`)}> Simulate navigation </button> <PageProgress progress={progress} visible={visible} /> </> ); }
03
Copy-Paste (Single File)
PageProgress.tsx
import { cn } from "@/lib/utils"; export interface PageProgressProps { progress: number; visible: boolean; } export function PageProgress({ progress, visible }: PageProgressProps) { return ( <div role="progressbar" aria-valuemin={0} aria-valuemax={100} aria-valuenow={progress} aria-hidden="true" className={cn( "pointer-events-none fixed left-0 top-0 z-200 h-0.5 bg-primary", "shadow-[0_0_8px_1px_rgba(70,40,241,0.7)]", "transition-opacity duration-300", visible ? "opacity-100" : "opacity-0" )} style={{ width: `${progress}%`, transition: `width ${progress === 0 ? "0ms" : progress === 100 ? "150ms" : "350ms"} ease-out, opacity 300ms`, }} /> ); }
04
Props
| Prop | Type | Default | Description |
|---|---|---|---|
progress | number | — | Current completion percentage from 0 to 100. |
visible | boolean | — | Controls the fade-in and fade-out visibility state. |