shadcn.io is not affiliated with official shadcn/ui
Reading Progress Metric Banner Block for Solid
A reading-progress banner for a long-form magazine: the article title, percent read and minutes left over a thin bar that follows the scroll of a small excerpt, driven by CSS scroll timelines where supported.
Installation
Overview
A reading-progress banner for Solid with Ark UI, for articles, guides and long documentation pages. Two bands sit between the page's solid rails with an interior rule and + marks between them: the first holds the article's title, the share read and the minutes left, with a thin bar under them; the second holds a small excerpt that scrolls. The bar follows the scroll. In browsers with CSS scroll timelines the bar is driven by the excerpt's own scroll position with no script; everywhere else, and with reduced motion, a scroll handler sets it, so it is always exact. The minutes left come from the words left at 238 a minute. It's built from Guides, with your theme's tokens for every colour. For magazines, blogs, changelogs and any page long enough to want a progress line.
FAQ
How does the bar follow the scroll without JavaScript?
The excerpt declares a named scroll timeline (scroll-timeline: --reading block) and the bar's fill plays the catalog's enter animation on that timeline, sliding in from the inline start as the excerpt scrolls from the top to the bottom. A timeline-scope on the section lets the bar, which is outside the excerpt, use it. That all sits behind @supports (animation-timeline: scroll()), so a browser without scroll timelines never sees it.
What do browsers without scroll timelines, or with reduced motion, get?
The same bar, set by a scroll handler: each scroll event reads how far the excerpt has moved and writes the width as a CSS variable. It is never eased, so it is exact and calm. The percentage and the minutes left are always set that way, in every browser, since they are text and need numbers. Reduced motion takes the scroll-driven animation off and uses the handler.
How do I make it follow the whole page instead of the excerpt?
Point it at the page: remove the excerpt, and replace scroll-timeline and timeline-scope with animation-timeline: scroll(root) on the fill. For the fallback, read window.scrollY against document.documentElement.scrollHeight - innerHeight in a passive scroll handler. Make the banner sticky top-0 if you want it to stay in view while the page moves.
How are the minutes left worked out?
The article has a word count (ARTICLE.words), the pace is ARTICLE.wordsPerMinute (238, the average adult silent-reading speed), and the minutes left are the words not yet read divided by that pace, rounded up. At 100% it says "Finished". The excerpt stands for the whole article here, so scrolling it to 64% means the article is 64% read.
Can the excerpt be scrolled with a keyboard?
Yes. It takes focus with Tab, shows a focus ring and scrolls with the arrow keys, Page Up and Page Down, Home and End; the bar follows. It is a labelled region named "Excerpt: scroll to read, the bar above follows". The bar itself is a picture and is hidden from assistive technology; the text beside it carries the numbers.