ComponentsNavigation

Reading progress

How far the reader is through an article or the page: a thin accent bar pinned to the top of the window (or inline), an announced value with minutes left, and an optional floating indicator. Tracks a target element by ref or selector, or the whole page.

WAI-ARIA progressbar role components/reading-progress.tsxtheme · material · accent · density · font

Writing a field guide

The first draft of a field guide is always too long. Every observation feels essential while you are standing in the marsh with wet boots and a notebook.

Editing is where the guide becomes useful. You keep the details that help someone recognise a heron at a distance, and drop the ones that only remind you of the morning.

A good entry answers three questions quickly: what it looks like, where you will find it, and what it is easily confused with.

Photographs help, but a short sentence about posture or movement often does more. Birds are identified by behaviour as much as by colour.

The last pass is for rhythm. Entries that read the same way are easier to scan, so the reader's eye always knows where to look next.

Installation

$ pnpm add @vamos-ui/react

The whole kit as one package — get updates by bumping the version. Add the styles to globals.css: @import "@vamos-ui/react/styles.css";

Usage

import { ReadingProgress } from "@vamos-ui/react";

const articleRef = React.useRef<HTMLElement>(null);
<ReadingProgress target={articleRef} minutes={8} indicator />
<article ref={articleRef}>…</article>

<ReadingProgress />  // the whole page

A target that ends near the bottom of the page counts as finished when the page can't scroll further.

For a purely decorative page bar with no announced value, ScrollProgress in @vamos-ui/react/motion uses CSS scroll timelines.

Examples

Whole page

Without a target the bar follows the page scroll. position="top" (default) pins it to the window.

Scroll this documentation page to move the bar.

API

ReadingProgress

PropTypeDefault
target
What is being read: a ref, an element or a CSS selector. Omit for the whole page.
RefObject<HTMLElement> | HTMLElement | string—
offset
The reading line as a share of the window height: progress is how far it has moved through the target.
number0.3
minutes
Reading time; adds "3 min left" to the announced value and the indicator.
number—
position
Pinned to the top or bottom of the window, or a bar in the flow.
"top" | "bottom" | "inline""top"
indicator
Floating pill (bottom end) with the percentage and minutes left while reading.
booleanfalse
portal
Render the pinned bar in the theme's portal container so sticky headers and transformed ancestors never clip it.
booleantrue when pinned
onProgressChange
Progress 0…1 as it changes.
(progress: number) => void—
labels
Dictionary namespace "readingProgress": label, minutesLeft, done.
Partial<ReadingProgressLabels>—

useReadingProgress(target?, options?)

PropTypeDefault
options
Same measuring as the component, for custom indicators.
{ offset?, onChange? }—
returns
progress 0…1; started once the target's top passes the reading line.
{ progress: number; started: boolean }—