TopProgress
The indeterminate bar a route wears while it fetches. Sweeps edge to edge from the seam, and holds a filled track rather than vanishing when motion is off.
Install
$ npx shadcn@latest add wisp.pouriah.com/r/top-progress.jsonLoader · CSSindeterminate
route fetching · indeterminate
"use client";
import * as React from "react";
import { cx } from "@pouriahlabs/wisp-ui";
/**
* TopProgress — the indeterminate bar a route wears while it fetches.
*
* A thin track with a seam-coloured comet sweeping edge to edge: the loader you
* pin to the top of a layout so a navigation has a heartbeat before its content
* arrives. It reports nothing about how far along the work is — that is the
* honest shape when you don't know — only that work is happening.
*
* The sweep is a compositor transform, so it never touches layout, and under
* reduced motion it holds a filled track rather than a bar parked off-screen: a
* still frame that still reads as loading.
*/
export interface TopProgressProps extends React.HTMLAttributes<HTMLDivElement> {
/** Token for the comet's leading edge. */
fromToken?: string;
/** Token for its trailing edge — the second half of the seam. */
toToken?: string;
/** Track thickness, as any CSS length. */
height?: string;
/** Seconds per sweep. */
duration?: number;
/** Accessible status text announced while the bar is on screen. */
label?: string;
}
export function TopProgress({
fromToken = "--wisp",
toToken = "--lantern",
height = "2px",
duration = 1.15,
label = "Loading",
className,
style,
...props
}: TopProgressProps) {
return (
<div
className={cx("wisp-progress", className)}
role="status"
aria-label={label}
style={
{
"--wisp-progress-from": `var(${fromToken})`,
"--wisp-progress-to": `var(${toToken})`,
"--wisp-progress-height": height,
"--wisp-progress-duration": `${duration}s`,
...style,
} as React.CSSProperties
}
{...props}
>
<span className="wisp-progress-bar" aria-hidden />
</div>
);
}
Certified against the contract
- ✓Reduced motion paints one composed still frame — never a blank box
- ✓Pauses off-screen and in hidden tabs
- ✓Re-reads design tokens when the theme changes
- ✓SSR-safe: no hydration mismatch, no layout shift
- ✓Decorative layers are aria-hidden and pointer-events-none
- ✓Device pixel ratio clamped
- ✓Zero runtime dependencies beyond React