VisorVisor
ComponentsData Display

Segmented Progress

Discrete per-step progress meter — N equal pill segments in a row, each individually expressing done, current, or pending state.

Default

Pass total and value to render a row of pill segments. Completed steps (indices 0..value-1) are filled with the primary color; remaining steps render as muted surface.

With current segment

Pass current (a 0-based index, typically equal to value) to render an in-progress gradient on the next segment — a primary-to-muted split at the ~55%/45% mark.

Sizes

Two segment heights for different surface densities. sm (6px) is the default and matches the brand-workbench prototype. md (8px) is slightly taller for increased visual weight.

Completion states

Each segment independently resolves to done, current, or pending:

Installation

npx visor add segmented-progress

This copies two files into your project:

  • components/ui/segmented-progress/segmented-progress.tsx — the component
  • components/ui/segmented-progress/segmented-progress.module.css — the styles

Usage

import { SegmentedProgress } from '@/components/ui/segmented-progress/segmented-progress';

export default function OnboardingProgress({ step, total }: { step: number; total: number }) {
  return (
    <SegmentedProgress
      total={total}
      value={step}
      current={step}
      aria-label={`Step ${step + 1} of ${total}`}
    />
  );
}

API Reference

SegmentedProgressProps

PropTypeDefaultDescription
total*numberTotal number of segments to render.
value*numberCount of completed segments — indices 0..value-1 render in the done state.
currentnumberOptional 0-based index of the in-progress segment, rendered with the primary-to-muted gradient. Typically equals value.
size'sm' | 'md''sm'Segment height — 6px (sm) or 8px (md).
aria-label*stringAccessible name for the progress bar.
classNamestringAdditional CSS class names to merge onto the element.

The component also accepts all standard <div> HTML attributes.

Accessibility

  • The root element has role="progressbar" with aria-valuemin={0}, aria-valuemax={total}, and aria-valuenow={value}.
  • An aria-label is required — describe the current step context (e.g. "Step 3 of 10" or "Brand elicitation: step 3 of 10 complete").
  • Individual segment <span> elements are presentational; the progressbar role carries all announcements.
  • Segment transitions are disabled under prefers-reduced-motion.