# Scroll Progress

> A React scroll progress pill with a reading ring that opens into a menu of sections.

- Type: React component (Navigation)
- Access: Free (the source is open to everyone)
- Version: 1.0.1
- Install: `npx wingo-ui@latest add scroll-progress`
- Docs: https://wingo-ui.com/components/scroll-progress

## Interaction

Scroll to fill the ring and watch the active section label crossfade in. Click the pill to morph it into a squircle menu, then tap any section to smooth-scroll there. From the keyboard, the menu opens with focus on the current section, the arrow keys, Home and End move between sections, and Escape closes it and hands focus back to the pill. Click outside to close it too.

## Installation

```bash
npx wingo-ui@latest add scroll-progress
```

The CLI adds the files, their dependencies and a version record for updates.

With shadcn: `npx shadcn@latest add https://wingo-ui.com/r/scroll-progress.json`

Files:

- `components/ui/scroll-progress.tsx`

npm dependencies: `npm i motion`

Wingo UI dependencies (installed automatically):

- [Motion presets](https://wingo-ui.com/components/motion) ([Markdown](https://wingo-ui.com/components/motion.md))
- [UIProvider](https://wingo-ui.com/components/ui-config) ([Markdown](https://wingo-ui.com/components/ui-config.md))

## Usage

```tsx
"use client"

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

const sections = [
  { id: "intro", label: "Introduction" },
  { id: "usage", label: "Usage" },
  { id: "faq", label: "FAQ" },
]

export function Demo() {
  const scrollRef = useRef<HTMLElement>(null)

  return (
    <main ref={scrollRef} className="relative h-full overflow-auto">
      <ScrollProgress
        containerRef={scrollRef}
        sections={sections}
        className="absolute"
        position="bottom-center"
      />

      <section id="intro">{/* ... */}</section>
      <section id="usage">{/* ... */}</section>
      <section id="faq">{/* ... */}</section>
    </main>
  )
}

// tracks the window with no container ref:
// <ScrollProgress sections={sections} />
```

## Props

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `sections?` | `Array<{ id: string; label: string }>` | `"[]"` | Ordered sections shown as the reader moves and listed in the menu. Each id must match an element id present in the scrolled content. Defaults to an empty list, which leaves just the ring. |
| `offset?` | `number` | `120` | Distance in pixels below the scroller's top edge that a section must cross to be marked active. |
| `size?` | `"sm" \| "md" \| "lg"` | `"md"` | Scale of the pill, the ring and the menu rows. On touch screens the pill and every row grow to at least 44px tall so they are easy to hit. |
| `position?` | `"bottom-center" \| "bottom-left" \| "bottom-right" \| "top-center" \| "top-left" \| "top-right"` | `"bottom-center"` | Where the pill is pinned. The menu grows away from that edge, and the safe-area insets of notched phones are added on top of inset. |
| `inset?` | `number` | `24` | Distance in pixels between the pill and the edges it is pinned to. |
| `showLabel?` | `boolean` | `true` | Shows the active section name next to the ring. Turn it off for a compact round button with just the ring. |
| `accentColor?` | `string` | `"auto"` | Color of the progress ring and the active section dot, any CSS color. Auto uses the foreground color of the theme. |
| `trackColor?` | `string` | `"auto"` | Color of the ring track behind the progress, any CSS color. Auto is the foreground color at 15% opacity. |
| `surfaceColor?` | `string` | `"auto"` | Any CSS color for the pill and the open menu. Auto is the page background at 70% over a blur. |
| `textColor?` | `string` | `"auto"` | Any CSS color for the labels, the dots, the row highlight and the ring (when accentColor and trackColor are auto). Auto is the foreground color. |
| `radius?` | `number` | `26` | Corner radius of the open menu in pixels. The rows follow it with a radius 12px smaller, and the closed pill is always fully round. |
| `triggerLabel?` | `string` | `"Show sections"` | Accessible name of the pill button. Screen readers hear it followed by the current section. |
| `currentLabel?` | `string` | `"current"` | The word between triggerLabel and the section name in the pill's accessible name: "Show sections, current: Pricing". |
| `listLabel?` | `string` | `"Sections"` | Accessible name of the open menu. |
| `containerRef?` | `React.RefObject<HTMLElement \| null>` |  | Scroll container to track and scroll within. Defaults to the window when omitted. |
| `className?` | `string` |  | Extra classes merged onto the root wrapper, which is fixed to the viewport at the chosen position. Pass absolute to pin it inside a relative panel instead. Any other <div> attribute is passed through too. |

## Parts

### ScrollProgressSection (type)

One entry of sections: { id, label }. id is the element id the menu scrolls to and the scrollspy watches.

## Examples

- **Long-form article**: The small pill in the bottom right with a blue ring; tap it to jump between the article's sections.
- **Ring only**: showLabel off keeps a compact round button with just the progress ring, here at the top right.
- **Product page**: Features, pricing and FAQ with an orange ring, centered at the top of the card.

## See also

- [Proximity Sidebar](https://wingo-ui.com/components/proximity-sidebar) ([Markdown](https://wingo-ui.com/components/proximity-sidebar.md))
- [Table Of Contents](https://wingo-ui.com/components/table-of-contents) ([Markdown](https://wingo-ui.com/components/table-of-contents.md))
- [Progress](https://wingo-ui.com/components/progress) ([Markdown](https://wingo-ui.com/components/progress.md))
- [Back To Top](https://wingo-ui.com/components/back-to-top) ([Markdown](https://wingo-ui.com/components/back-to-top.md))
- [useScrollState](https://wingo-ui.com/components/use-scroll-state) ([Markdown](https://wingo-ui.com/components/use-scroll-state.md))

---

Canonical: https://wingo-ui.com/components/scroll-progress
More components: https://wingo-ui.com/components · Index for agents: https://wingo-ui.com/llms.txt
