Skip to content
Ndop UI

Progress

Displays how far a task has got.

Setting up your workspace
import { Component } from '@angular/core';
import { Progress, ProgressIndicator } from '@/ui/progress/progress';

/** A progress bar named by a visible label. */
@Component({
  selector: 'example-progress-demo',
  imports: [Progress, ProgressIndicator],
  template: `
    <div class="grid w-full max-w-sm gap-2">
      <span id="progress-demo-label" class="text-sm font-medium"
        >Setting up your workspace</span
      >
      <div ndProgress [value]="66" aria-labelledby="progress-demo-label">
        <div ndProgressIndicator></div>
      </div>
    </div>
  `,
})
export class ProgressDemoExample {}

A progress bar shows how far a task has got: an upload, an installation, the steps of a form. It's announced as a progressbar with its value and percentage, and fills from the start side, so from the right in right-to-left layouts. Leave value empty while you can't say how far it has got, and it pulses instead.

Installation

npx @ndop/cli add progress

Usage

import { Progress, ProgressIndicator } from '@/ui/progress/progress';
<div class="grid w-full max-w-sm gap-2">
  <span id="progress-demo-label" class="text-sm font-medium"
    >Setting up your workspace</span
  >
  <div ndProgress [value]="66" aria-labelledby="progress-demo-label">
    <div ndProgressIndicator></div>
  </div>
</div>

Examples

Progress upload

Files uploading, each with its progress and percentage.

  • report.pdf100%
  • photos.zip45%
  • video.mp4Waiting
import { Component } from '@angular/core';
import { Progress, ProgressIndicator } from '@/ui/progress/progress';

/**
 * Files uploading, each with its own bar and percentage; the last one
 * waits to start, so its bar is indeterminate.
 */
@Component({
  selector: 'example-progress-upload',
  imports: [Progress, ProgressIndicator],
  template: `
    <ul class="grid w-full max-w-sm gap-4">
      @for (file of files; track file.name) {
        <li class="grid gap-2">
          <div class="flex justify-between text-sm">
            <span [id]="'progress-upload-' + $index" class="font-medium">{{
              file.name
            }}</span>
            <span class="text-muted-foreground">{{
              file.value === null ? 'Waiting' : file.value + '%'
            }}</span>
          </div>
          <div
            ndProgress
            [value]="file.value"
            [attr.aria-labelledby]="'progress-upload-' + $index"
          >
            <div ndProgressIndicator></div>
          </div>
        </li>
      }
    </ul>
  `,
})
export class ProgressUploadExample {
  protected readonly files = [
    { name: 'report.pdf', value: 100 },
    { name: 'photos.zip', value: 45 },
    { name: 'video.mp4', value: null },
  ];
}

Accessibility

Implements the progressbar role pattern of the WAI-ARIA Authoring Practices.

Focus

  • The progress bar never receives focus and never changes focus.

Right-to-left

The indicator fills from the start side: from the right in right-to-left layouts.

API reference

Progress

[ndProgress]role progressbar

A progress bar (@ndop/primitives/progress): how far a task has got, from 0 to max, or indeterminate while value is null. Give it a name with aria-label or aria-labelledby, and put a ndProgressIndicator inside.

Manages aria-valuemin, aria-valuemax, aria-valuenow, aria-valuetext.

Progress binding Type Default
[class]
Extra classes, merged last so they win.
string''
[value]
How far the task has got, from 0 to max; null while unknown.
number | nullnull
[max]
The value of a finished task.
number100
Data attribute Values
data-slotprogress
data-state —
data-value —
data-max —

ProgressIndicator

[ndProgressIndicator]

The filled part of a progress bar. It fills from the start side, so from the right in right-to-left layouts, and pulses across the whole bar while indeterminate.

ProgressIndicator binding Type Default
[class]
Extra classes, merged last so they win.
string''
Data attribute Values
data-slotprogress-indicator
data-state —

Agent notes

Do

  • Name it with aria-label or aria-labelledby, such as "Upload".
  • Show the percentage or what's left in text next to it, too.
  • Use a Spinner instead when there's no measure of progress at all.

Don't

  • Don't use it to show a static quantity, such as storage used; that's a meter.
  • Don't move it backwards.