# Progress Log

> The steps of a long piece of work, like an import, a setup, or a deploy. The list grows while it runs, then folds into one line, like Done in 34s, 5 steps. A failure stays open and says why.

- Name: `progress-log`
- Status: beta
- Categories: ai, feedback
- File: the install writes `progress-log.tsx` to your `ui` alias, `@/components/ui` by default.
- npm packages: `@base-ui/react`, `class-variance-authority`. The install adds them.
- Other registry items: `@arbokui/spinner`, `@arbokui/timeline`. The install adds them.
- Gallery: https://arbokui.com/components/progress-log
- Registry item: https://arbokui.com/r/progress-log.json

## Install

1. Add the registry to `components.json`. Do this first, once:

   ```bash
   npx shadcn@latest registry add "@arbokui=https://arbokui.com/r/{name}.json"
   ```

   The command writes this entry. You can also add it by hand:

   ```json
   {
     "registries": {
       "@arbokui": "https://arbokui.com/r/{name}.json"
     }
   }
   ```

   Without this step, the shadcn CLI looks up `@arbokui` in a public list that Arbokui does not control.

2. Add the theme once per app. It replaces your color tokens with ones checked for contrast:

   ```bash
   npx shadcn@latest add @arbokui/theme
   ```

3. Add the component:

   ```bash
   npx shadcn@latest add @arbokui/progress-log
   ```

## Use it for

- Show the steps of work that takes a while, like importing a file, setting up an account, or publishing a site.
- Pass loading while it runs. Add each step to the end of steps as it starts. The last one spins.
- Set loading to false when it is done. The list folds into one line that opens again.
- Pass total when you know how many steps there are. The line then counts them, like Step 3 of 5.
- If it stops, set loading to false and pass error in plain words. The last step turns red, and the list stays open.
- Pass duration, like 34s, and keep it current while loading for a live timer. The folded line uses it.
- Give each step an id, so a new one fades in and the rest stay still.

## Avoid it for

- A single wait with no steps. Use Spinner.
- One job with its details and result. Use JobCard.
- Progress you can measure, like 3 of 5 files sent, with no steps to show. Use Progress.
- An agent's own steps while it thinks. Use ThinkingState.

## Props

- `steps`: `{ id?: string; label: ReactNode; detail?: ReactNode; time?: string }[]`. Required. The steps so far, oldest first. While loading, the last one is under way.
- `loading`: `boolean`. Default `false`. The work is still going. The list stays open and grows. When it turns false, the list folds into one line.
- `total`: `number`. How many steps there will be. The line counts them while loading, like Step 3 of 5.
- `duration`: `string`. How long it has run, or ran in all, like "34s".
- `error`: `ReactNode`. The work stopped on its last step. Say why in plain words. It shows under the line, and the list stays open.
- `label`: `ReactNode`. Default `"Working"`. The line while loading. It pulses slowly.
- `summary`: `ReactNode`. The folded line once done. Default "Done in 34s, 5 steps", or "Failed at step 3 of 5, after 34s" with an error.
- `defaultOpen`: `boolean`. Starts open or folded. Default: open while loading or failed, folded when done.
- `open`: `boolean`. Controls whether it is open. Pair it with onOpenChange. Then it no longer folds itself.
- `onOpenChange`: `(open: boolean) => void`. Called when it opens or folds.
- `className`: `string`. Extra classes on the root. Later classes win.

## Accessibility

- The line is one button that opens and folds the steps, and it tells screen readers if it is open.
- The steps are an ordered list named Steps. The one under way says (working), and a failed one says (failed), to screen readers.
- Each new step is said politely in a hidden status region, and so is the summary when the work ends.
- A failure is shown three ways: the words Failed at, an icon, and the danger color. The reason is plain text under the line.
- The spinners and the pulse stop when the theme turns motion off, and for reduced motion. The list then opens and folds at once.

## Examples

### While running

```tsx
<ProgressLog
  loading
  total={4}
  duration="12s"
  steps={[
    { id: "upload", label: "Uploaded contacts.csv", detail: "2,400 rows" },
    { id: "check", label: "Checking each row" },
  ]}
/>
```

### Done

```tsx
<ProgressLog
  duration="34s"
  steps={[
    { id: "upload", label: "Uploaded contacts.csv" },
    { id: "check", label: "Checked 2,400 rows" },
    { id: "merge", label: "Merged 64 duplicates" },
  ]}
/>
```

### Failed

```tsx
<ProgressLog
  total={4}
  duration="9s"
  error="Row 214 has no email. Fix it and import again."
  steps={[
    { id: "upload", label: "Uploaded contacts.csv" },
    { id: "check", label: "Checking each row" },
  ]}
/>
```
