# Progress

Shows that work is under way: a determinate bar for work of known size, a spinner for a short wait inside the control that started it.

* Kind: component
* Page: https://design.werklist.com/components/progress
* Version: 2.1.2

## When to use it

* Import, upload or sync of known size, such as importing candidates or uploading passports: bar where the work started
* A button's action takes a moment, such as Send offer: the button is busy at once and its spinner shows after 300 ms (--duration-slow)
* More rows load at the end of a list: 20 px spinner in the footer

## When not to use it

* A page or panel loading content: Skeleton
* Long work with no size and no way to learn it: say it in words
* More than one indicator for one action
* A blocking overlay with a spinner

## Anatomy

* bar: 4 px high; fully round (--radius-full)
* track: the fill of a control (--surface-control)
* fill: brand blue, at least 3:1 against the track in both themes (--brand-blue)
* label row: label in Caption, 12 px, medium, --text, on the left; value in Caption small, 11 px, tabular, --text-muted, on the right (--type-product-caption, --type-product-caption-small, --text, --text-muted)
* status row: what is happening on the left, counts on the right, Caption small, 11 px, --text-muted, tabular (--type-product-caption-small, --text-muted)
* rhythm: 6 px between label row, bar and status row
* cancel: a small quiet button, Cancel, at the right of the label row, only when stopping loses nothing
* indeterminate segment: a third of the track at its start, a --brand-blue gradient that is full in the middle and 30 percent at both ends; pulses from 100 to 50 percent opacity over 2,000 ms, cubic-bezier(0.4, 0, 0.6, 1); hidden under reduced motion
* spinner: an open circle with round ends, in the ink of the control that holds it; one turn per second at a steady speed (--text-muted, --on-brand)

## Variants

* determinate bar: known size
* indeterminate bar: the start of a bar whose size is unknown
* spinner: a short wait inside the control, row or list footer that started it

## Sizes

* spinner in controls and rows: height 16 px
* spinner in panels and list footers: height 20 px

## States

* advancing: fill width animates to the new value over 500 ms (--ease-standard)
* size becomes known: the segment gives way to the fill at the true value
* stalled: after 10 seconds without movement the status says in words what the work waits for
* failed: status row replaced by the failure and what to do, in --error-ink; fill stays (--error-ink)
* done: the bar leaves; a toast or a notification reports the end
* spinner delay: the control is busy at once; the spinner appears after 300 ms (--duration-slow)
* reduced motion: the bar steps to each value; the spinner stays still and pulses from 100 to 50 percent opacity over 2,000 ms; the moving segment is hidden

## Keyboard

* Tab: reaches Cancel when present; the bar and the spinner take no focus

## Accessibility

* bar: role progressbar, aria-label from the label, aria-valuemin 0, aria-valuemax 100, aria-valuenow when known and absent when unknown
* no live region on the bar; the end is announced once by the toast or notification that reports it
* spinner: aria-hidden; its host carries aria-busy true and keeps its name
* fill against track at least 3:1 in both themes

## Content

* label: a verb ending in ing and its object, no ellipsis, no period
* status: numbers the reader can check, formatted in the app's locale; a percentage only beside them
* no time estimate unless the work is steady

## Tokens

* --type-product-caption
* --type-product-caption-small
* --surface-control
* --brand-blue
* --radius-full
* --text
* --text-muted
* --error-ink
* --on-brand
* --duration-slow
* --ease-standard
