Skip to content

feat(ReadingProgressBar): scroll-progress bar for long-form pages - #396

Open
ebellamy-bh wants to merge 2 commits into
mainfrom
feat/reading-progress-bar
Open

feat(ReadingProgressBar): scroll-progress bar for long-form pages#396
ebellamy-bh wants to merge 2 commits into
mainfrom
feat/reading-progress-bar

Conversation

@ebellamy-bh

Copy link
Copy Markdown

Ports the Enterprise Health frontdoor's reading-progress bar — the thin bar pinned to the viewport top that fills as the reader scrolls a long-form page.

What it does

  • Tracks document scroll and fills 0–100%, clamped, with unscrollable documents handled
  • rAF-coalesced scroll handler (one state update per frame — an upgrade over the source's per-event updates), passive listener, resize-aware
  • Decorative by design (aria-hidden); token-colored with bg-primary-500 default and barClassName/className overrides for color and thickness
  • Pairs with TableOfContents and SectionSpyNav (feat(SectionSpyNav): sticky in-page section nav with sliding underline #392) as the third piece of long-form wayfinding

Screenshots

Mid-article, ~55% read:

Light Dark
ReadingProgressBar light ReadingProgressBar dark

Provenance

Port of enterprise-health-frontdoor/components/ui/ReadingProgressBar.tsx, retokened from the EH gilt to the primary scale.

Testing

  • 4 unit tests (0% at top, scroll tracking, 100% clamp + unscrollable documents, aria-hidden + custom bar class) with mocked scroll metrics and synchronous rAF
  • 2 stories: default and custom color/thickness over a long article
  • typecheck / lint / format / rtl:scan clean; combined batch suite 622/622

Ported from the Enterprise Health frontdoor: a thin aria-hidden bar
pinned to the viewport top tracking document scroll. Generalized to
token colors (bg-primary-500 default, barClassName override) with an
rAF-coalesced scroll handler.
Copilot AI lite review requested due to automatic review settings August 23, 2026 03:42

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new ReadingProgressBar component to the UI library for long-form pages: a thin, fixed bar at the top of the viewport that fills based on document scroll progress. This complements existing long-form wayfinding components (e.g., TableOfContents, SectionSpyNav).

Changes:

  • Introduces ReadingProgressBar React component with scroll/resize tracking and class overrides.
  • Adds unit tests covering initial state, scroll tracking, clamping/unscrollable docs, and aria-hidden + custom bar class.
  • Adds Storybook stories and wires the component into the package exports/build entrypoints.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
tsup.config.ts Adds ReadingProgressBar entry to the build export map.
src/index.ts Re-exports ReadingProgressBar from the package root.
src/components/ReadingProgressBar/ReadingProgressBar.tsx Implements the fixed, scroll-tracking progress bar.
src/components/ReadingProgressBar/ReadingProgressBar.test.tsx Adds unit tests for scroll progress behavior and props.
src/components/ReadingProgressBar/ReadingProgressBar.stories.tsx Adds Storybook coverage for default and customized styling.
src/components/ReadingProgressBar/index.ts Component barrel export for local imports and root export.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread src/components/ReadingProgressBar/ReadingProgressBar.tsx Outdated
Comment thread src/components/ReadingProgressBar/ReadingProgressBar.tsx Outdated
@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Aug 23, 2026

Copy link
Copy Markdown

Deploying ui with  Cloudflare Pages  Cloudflare Pages

Latest commit: 8550366
Status: ✅  Deploy successful!
Preview URL: https://8b7b5efb.ui-6d0.pages.dev
Branch Preview URL: https://feat-reading-progress-bar.ui-6d0.pages.dev

View logs

…o 0, click-through bar

- Progress is clamped to 0–100 so iOS rubber-band overscroll (negative
  scrollTop) cannot render a negative-width fill
- The fixed overlay gets pointer-events-none so it never intercepts
  clicks on content beneath it
Copilot AI review requested due to automatic review settings August 23, 2026 04:29

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 6 out of 6 changed files in this pull request and generated no new comments.

Suppressed comments (3)

Previously missed (3) — in code that hasn't changed since the last review.

src/components/ReadingProgressBar/ReadingProgressBar.tsx:9

  • ReadingProgressBarProps extends React.HTMLAttributes<HTMLDivElement>, which includes children, but this component always renders its own internal children and will ignore any consumer-provided children. Consider omitting children from the props type to avoid a misleading API (matches patterns like DashboardWidgetTableProps in src/components/DashboardWidget/DashboardWidget.tsx:296).
export interface ReadingProgressBarProps extends React.HTMLAttributes<HTMLDivElement> {
  /** Class for the filled bar (default `bg-primary-500`). */
  barClassName?: string;
}

src/components/ReadingProgressBar/ReadingProgressBar.tsx:64

  • Because {...props} is spread after aria-hidden on the outer <div>, consumers can override aria-hidden (e.g. aria-hidden={false}) even though the component is documented as “purely decorative”. If decorative is intended to be enforced, spread props first so aria-hidden="true" cannot be overridden.
    <div
      ref={ref}
      aria-hidden="true"
      className={cn(
        'pointer-events-none fixed inset-x-0 top-0 z-50 h-1 bg-transparent',
        className
      )}
      {...props}
    >

src/components/ReadingProgressBar/ReadingProgressBar.tsx:75

  • Most forwardRef components in this codebase set a displayName for clearer React DevTools output (e.g. Button.displayName in src/components/Button/Button.tsx:186, Input.displayName in src/components/Input/Input.tsx:150). Adding one here would improve debugging ergonomics.
});

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants