Redpanda UI
RC
Redpanda UI

Scroll Progress

A scroll progress component that displays the progress of the scroll.

Made by imskyleen
Loading component...

When to use

Scroll Progress provides visual feedback about reading progress through content. Use this decision tree to determine when it's appropriate:

Installation

Usage

Global Page Scroll Progress

Track the scroll progress of the entire page:

import { ScrollProgress } from "@/components/redpanda-ui/scroll-progress"

// Add to your main layout or page
function App() {
  return (
    <>
      <ScrollProgress />
      <main>
        {/* Your page content */}
        <article className="max-w-4xl mx-auto px-6 py-12">
          <h1>Long Article Title</h1>
          <p>Very long content that will require scrolling...</p>
          {/* More content */}
        </article>
      </main>
    </>
  )
}

Local Container Scroll Progress

Track scroll progress within a specific scrollable container:

<ScrollProgress className="h-[400px] w-full border rounded-lg p-6">
  <div className="space-y-6">
    <h2>Scrollable Content Section</h2>
    <p>This content will scroll within the container...</p>
    {Array.from({ length: 20 }).map((_, i) => (
      <div key={i} className="p-4 border rounded">
        <h3>Section {i + 1}</h3>
        <p>Content for section {i + 1} goes here. This demonstrates the local scroll progress tracking.</p>
      </div>
    ))}
  </div>
</ScrollProgress>

Custom Styled Progress Bar

Customize the appearance of the progress bar:

<ScrollProgress
  progressProps={{
    className: "fixed z-50 top-0 inset-x-0 h-2 bg-gradient-to-r from-blue-500 to-purple-500 origin-left",
    style: {
      boxShadow: "0 0 10px rgba(59, 130, 246, 0.5)"
    }
  }}
>
  <div className="h-[200vh] p-6">
    <h1>Custom Styled Progress</h1>
    <p>Long content with a custom gradient progress bar...</p>
  </div>
</ScrollProgress>

Reading Progress for Articles

Ideal for blog posts and articles:

function BlogPost() {
  return (
    <>
      <ScrollProgress 
        progressProps={{
          className: "fixed z-50 top-0 inset-x-0 h-1 bg-primary origin-left transition-opacity duration-300"
        }}
      />
      <article className="max-w-2xl mx-auto px-4 py-16">
        <header className="mb-12">
          <h1 className="text-4xl font-bold mb-4">How to Build Better UIs</h1>
          <p className="text-muted-foreground">A comprehensive guide...</p>
        </header>
        
          {/* Long article content */}
          <Text variant="large">Your article content goes here...</Text>
        
      </article>
    </>
  )
}

Multiple Progress Indicators

Use different progress bars for different sections:

<div className="space-y-8">
  <ScrollProgress 
    className="h-[300px] border rounded-lg p-4"
    progressProps={{
      className: "absolute top-0 inset-x-0 h-1 bg-blue-500 origin-left"
    }}
  >
    <h3>Section 1</h3>
    <div className="space-y-4">
      {/* Content for section 1 */}
    </div>
  </ScrollProgress>
  
  <ScrollProgress 
    className="h-[300px] border rounded-lg p-4"
    progressProps={{
      className: "absolute top-0 inset-x-0 h-1 bg-green-500 origin-left"
    }}
  >
    <h3>Section 2</h3>
    <div className="space-y-4">
      {/* Content for section 2 */}
    </div>
  </ScrollProgress>
</div>

Anatomy

The Scroll Progress component uses Motion/Framer Motion to create smooth scroll-tracking animations:

<ScrollProgress> Component
├── <motion.div> Progress Bar
│   ├── Fixed Positioning (global) | Absolute (local)
│   ├── scaleX Animation - horizontal progress indicator
│   ├── useSpring Hook - smooth animation transitions
│   │   ├── stiffness: 250 - animation responsiveness
│   │   ├── damping: 40 - bounce control
│   │   └── bounce: 0 - no overshoot
│   └── Visual Styling
│       ├── height: h-1 (4px) default
│       ├── background: bg-primary
│       ├── origin: origin-left (scales from left)
│       └── z-index: z-50 (above other content)
├── Scroll Detection
│   ├── useScroll Hook - tracks scroll position
│   ├── scrollYProgress - normalized 0-1 value
│   └── Container targeting (global vs local)
└── Content Container (local mode only)
    ├── Scrollable wrapper - overflow-y-auto
    ├── Height management - h-full default
    └── Content rendering area

Animation Flow:
├── Scroll Event → useScroll → scrollYProgress (0-1)
├── useSpring → smooth value transformation
├── scaleX style → visual progress bar width
└── Real-time updates as user scrolls

Positioning Modes:
├── Global Mode (no children)
│   ├── Tracks document scroll
│   ├── Fixed positioning
│   └── Full viewport width
└── Local Mode (with children)
    ├── Tracks container scroll
    ├── Absolute/relative positioning
    └── Container-specific width

Key Features:

  • Smooth Animation: Spring-based physics for natural motion
  • Dual Mode: Global page tracking or local container tracking
  • Customizable Styling: Full control over appearance and positioning
  • Performance Optimized: Uses requestAnimationFrame for smooth updates
  • Responsive: Adapts to container width automatically
  • Zero Configuration: Works out of the box with sensible defaults

Props

Prop

Type

Credits

Built by malinskibeniamin. The source code is available on GitHub.

On this page