# Deploy Log

> An animated deploy log for React and shadcn, streaming build output under pinned stage headers.

A deploy's build log under a status header, with stage headers that pin and an elapsed time that rolls. Lines stream in flat and the log follows the newest; on failure the first error line shakes once and the status pill turns Failed.

Also known as a build log.

- Tier: Eased Pro
- Interaction: Scroll
- Page: https://eased.dev/components/deploy-log
- Installs: motion

## Install

Deploy Log ships with Eased Pro (https://eased.dev/#pricing). Members add the `@eased-pro` registry with their token (https://eased.dev/account), then run:

```bash
npx shadcn add @eased-pro/deploy-log
```

A deploy's build output under a status header, built on timeline-core's event model and chat-core's stick-to-bottom scrolling.

## When to use

- A deployment or build detail page that streams logs as they arrive.
- Job output in a CI or agent product, where stages and a pass/fail state matter.

## When not to use

- Scripted, illustrative commands: use [Terminal](/components/terminal).
- Searching or filtering a large log: a virtualised log explorer fits better.
- A dependency graph of jobs: use [CI Pipeline](/components/ci-pipeline).

## Usage

```tsx example.tsx
import { DeployLog } from "@/components/eased/deploy-log/deploy-log";

<DeployLog
  className="h-96"
  status="building"
  startedAt={startedAt}
  environment="Production"
  source="main · 4f9c2ab"
  lines={[
    { id: "1", at: t0, kind: "install", title: "pnpm install --frozen-lockfile" },
    { id: "2", at: t1, kind: "build", title: "Type error: Property 'currency' does not exist", tone: "danger" },
  ]}
/>
```

## API reference

### DeployLog

| Prop | Type | Default | Description |
|---|---|---|---|
| `lines` | `TimelineEvent[]` | | Lines so far, oldest first. `title` is the text, `kind` the stage, `tone` the level (`warning`, `danger`), `at` when it printed. |
| `status` | `"queued" \| "building" \| "ready" \| "error" \| "canceled"` | | Drives the pill, the counter and the stage marks. |
| `startedAt` / `endedAt` | `number` | | Epoch ms; the counter rolls while building and freezes at `endedAt`. |
| `environment` | `string` | | Shown beside the status, e.g. "Production". |
| `source` | `ReactNode` | | A muted line under it: branch, commit, message. |
| `stageLabels` | `Record<string, string>` | | Display names per stage id. Default: the id, capitalised. |
| `label` | `string` | `"Build log"` | Accessible name of the log. |
| `logRef` | `RefObject<HTMLDivElement>` | | The scrolling log, e.g. to scrub it to the top before a replay. Remount (`key`) to start a new run stuck to the bottom. |
| `className` | `string` | `""` | Give it a height; the log scrolls inside. |

## Accessibility

- The status pill is a `role="status"` region; the log is `role="log"` (polite, additions only) and keyboard-scrollable.
- Each stage is a named `section` with an `h3`; line numbers are hidden from assistive tech.
- The elapsed counter is read as "41 seconds", not digit by digit.

## Motion

Lines arrive with no per-line animation (rule 84) and the log follows the newest on a smooth spring until you scroll up. Stage headers are sticky, so the current stage pins while its lines scroll past. A stage's spinner swaps (y + blur) to a check or cross that draws on the snappy spring. The first error line shakes once, 5px, over 400ms; the pill re-tints in 150ms and its label swaps. Reduced motion: no shake, marks cross-fade, scrolling jumps.

## Notes for AI

Append lines as they stream and set `status` from your deploy API; the component works out stage boundaries, stage times and which line to shake. Keep `kind` stable per stage.

Don't animate lines yourself and don't wrap it in a scroll container: it scrolls and follows on its own.

## Related

- [CI Pipeline](/components/ci-pipeline): the jobs around this log.
- [Terminal](/components/terminal): scripted, typed commands.
