Scroll Progress
newA hairline that fills as the page or a container scrolls.
How the tokens are layered
The stylesheet has two layers. The palette holds every raw value and nothing else: a ramp of neutrals and the four status ramps, green, amber, blue and red, shared by both themes.
The semantic layer names roles and points them at palette steps. Components reference roles, never steps, so a theme is a list of assignments rather than a second copy of every rule.
Two accents
Primary is the action color and stays neutral. Brand is the identity color, used for focus, selection and checked state. Keeping them apart means a new brand color never repaints every button.
Dark mode
The dark theme re-points the same roles at darker steps. Borders and inputs become translucent white, so they read on any surface without a dedicated dark value per component.
To add a role, add it to the semantic layer in both themes and expose it to Tailwind. Nothing in a component ever needs a hex.
Installation
npx shadcn@latest add @blank/scroll-progressUsage
import { ScrollProgress } from "@/components/ui/scroll-progress"<ScrollProgress />On its own it tracks the page and is pinned to the top of the viewport. Pass
container to track a scrollable element instead, and position the bar
yourself, for example with sticky top-0 as its first child.
The bar is brand. It only moves when the reader scrolls, so there is
nothing to turn off for reduced motion.
Props
| Prop | Type | Default |
|---|---|---|
container | RefObject<HTMLElement> | the page |
className | string | — |