# CI Pipeline

> An animated CI pipeline for React and shadcn, showing jobs as a graph, with retry for failed branches.

A CI run as a graph of jobs whose edges draw as each job hands off to the next. A running job's spinner turns into a check that draws itself, a failure skips everything downstream, and Retry rewinds the failed branch.

- Tier: Eased Pro
- Interaction: Loading
- Page: https://eased.dev/components/ci-pipeline
- Installs: motion

## Install

CI Pipeline 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/ci-pipeline
```

A CI run as a graph of jobs on flow-core: auto layout, edges drawn on `pathLength`, and status propagation from thinking-core's `StepStatus`.

## When to use

- A CI, build or workflow product's run page, where jobs depend on each other.
- Any DAG of steps with a live state: data pipelines, agent workflows, release trains.

## When not to use

- A linear list of steps: a step rail or [Agent Run](/components/agent-run) reads faster.
- The log of one job: use [Deploy Log](/components/deploy-log).

## Usage

```tsx example.tsx
import { CIPipeline, retryFailed } from "@/components/eased/ci-pipeline/ci-pipeline";
import { stepFlow } from "@/components/eased/_primitives/flow-core/flow-core";

const [graph, setGraph] = useState(run);
// Each beat from your CI API (or stepFlow in a demo) moves jobs forward.
<CIPipeline graph={graph} label="Run #1284" onRetry={() => setGraph(retryFailed)} />;
```

## API reference

### CIPipeline

| Prop | Type | Default | Description |
|---|---|---|---|
| `graph` | `FlowGraph` | | Jobs as nodes (`id`, `label`, `status`, `detail`, `startedAt`, `endedAt`), needs as edges. |
| `selected` / `onSelectedChange` | `string` / `(id) => void` | | The job shown in the footer. Default: the failed job, else the first running one. |
| `onRetry` | `() => void` | | Shows Retry failed when a job has failed. |
| `label` | `ReactNode` | | Leading text in the summary row. |
| `direction` | `"LR" \| "TB"` | `"LR"` | Columns of jobs, or stages stacked top to bottom for a narrow panel. |
| `nodeWidth` / `nodeHeight` | `number` | `136` / `48` | Job size in px. Under 44px tall a job shows only its name; the footer carries its detail. |
| `rankGap` | `number` | `36` | Space between stages in px. |
| `className` | `string` | `""` | Appended to the root. |

### retryFailed(graph)

Returns the graph with every failed job, and everything it skipped, back to pending.

## Keyboard

| Key | Action |
|---|---|
| `Tab` | Moves through the jobs, then Retry. |
| `Enter` / `Space` | Selects a job (`aria-pressed`). |

## Accessibility

- Each job is a button named "E2E tests: Failed, 2 specs failed"; the canvas is a named group.
- The run status is a `role="status"` region; job and time counts are read as sentences.

## Motion

Edges draw from source to target over 0.5s as a job hands off and retract faster (0.6×, ease-in) on retry; skipped edges turn dashed. A job's spinner swaps (y + blur) to a check or cross that draws on the snappy spring. The canvas glides on the smooth spring to keep running jobs a third of the way in, and stops the moment you scroll it. Counts roll. Reduced motion: edges and scroll jump, marks cross-fade.

## Notes for AI

Feed it your CI's jobs as a flow-core graph and update statuses as they change; layout, edge state and the summary are derived. Put a short progress string in `detail` while running and a result once settled.

Don't position nodes yourself or animate edges: `layoutFlow` and `FlowEdgePath` already do both.

## Related

- [Deploy Log](/components/deploy-log): one job's output.
- [Agent Run](/components/agent-run): a linear run of steps.
