# Multi-Step Pipeline Tracker

Multi-Step Pipeline Tracker [#multi-step-pipeline-tracker]

The **MultiStepPipelineTracker** is a horizontal numbered-step progress indicator (active / completed / pending) that maps directly to `usePipeline`'s `onProgress` (`{ currentStep, completed, total }`). `StagePipelineTracker` is a single-stage label + 0–100 bar for ingest; `StepsPlan` is a vertical connector-bar outline with expandable per-step detail; and `InferenceQueueSurface` visualizes pending tasks grouped by priority (interactive / background) over `useInferenceQueue`.

Preview [#preview]

```tsx
'use client';

/**
 * @file pipeline-tracker-demo.tsx
 * @description Docs preview for `MultiStepPipelineTracker`. Shows the numbered
 * step indicator, the stage+percentage variant, the Steps/Plan outline, and the
 * inference-queue surface — driven by a simulated progress loop.
 */
import * as React from 'react';
import {
  InferenceQueueSurface,
  MultiStepPipelineTracker,
  StagePipelineTracker,
  StepsPlan,
  type PlanStep,
  type QueuedTask,
} from '@/components/pipeline-tracker';

const STEPS = ['Load', 'Chunk', 'Embed', 'Index'];

const PLAN: PlanStep[] = [
  { id: 'a', title: 'Parse documents', status: 'completed', detail: 'Extracted text from 12 PDFs.' },
  { id: 'b', title: 'Embed chunks', status: 'active', detail: 'Running bge-small on 340 chunks.' },
  { id: 'c', title: 'Build index', status: 'pending' },
];

const QUEUE: QueuedTask[] = [
  { id: '1', label: 'Answer current question', priority: 'interactive' },
  { id: '2', label: 'Re-embed updated doc', priority: 'background' },
  { id: '3', label: 'Warm reranker model', priority: 'background' },
];

export default function PipelineTrackerDemo() {
  const [completed, setCompleted] = React.useState(0);
  const [percent, setPercent] = React.useState(0);

  React.useEffect(() => {
    const id = window.setInterval(() => {
      setCompleted((c) => (c >= STEPS.length ? 0 : c + 1));
      setPercent((p) => (p >= 100 ? 0 : p + 20));
    }, 1200);
    return () => window.clearInterval(id);
  }, []);

  return (
    <div className="flex w-full max-w-xl flex-col gap-6">
      <MultiStepPipelineTracker
        steps={STEPS}
        completed={completed}
        currentStep={STEPS[completed]}
      />
      <StagePipelineTracker stage="Embedding chunks" percent={percent} />
      <StepsPlan steps={PLAN} />
      <InferenceQueueSurface tasks={QUEUE} />
    </div>
  );
}
```

Installation [#installation]

```bash
npx shadcn@latest add @localmode/ui/conversation/pipeline-tracker
```

Data source & dependencies [#data-source--dependencies]

**Data source:** renders the step/progress shape you pass — works with any backend. Recommended producer: `usePipeline` progress and `useInferenceQueue` from `@localmode/react` (on-device, optional).

* `clsx` + `tailwind-merge` — via the shared `cn()` util (installed automatically as a registry dependency)

Files installed [#files-installed]

* `pipeline-tracker.tsx` — `MultiStepPipelineTracker`, `StagePipelineTracker`, `StepsPlan`, `InferenceQueueSurface`
* `lib/utils.ts` — the `cn()` helper (if not already present)

Props [#props]

**MultiStepPipelineTracker**

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `steps` | `array` | — | **Required.** Ordered step labels. |
| `completed` | `number` | — | **Required.** Number of completed steps (e.g. `progress.completed`). |
| `currentStep` | `string` | — | The currently active step label (e.g. `progress.currentStep`). |

Examples [#examples]

Track pipeline progress [#track-pipeline-progress]

```tsx
import { usePipeline } from '@localmode/react';
import { MultiStepPipelineTracker } from '@/components/pipeline-tracker';

const { progress } = usePipeline(steps);

<MultiStepPipelineTracker
  steps={['Chunk', 'Embed', 'Index']}
  completed={progress?.completed ?? 0}
  currentStep={progress?.currentStep}
/>
```

Customization [#customization]

Use `StagePipelineTracker` for single-stage ingest with a percentage bar, or `StepsPlan` for an editable plan outline. The queue surface is presentational over `useInferenceQueue` — map your pending tasks into `QueuedTask[]`.

These primitives are presentational and hook-driven: they render props and emit callbacks, holding only local view state. The orchestration state (e.g. `usePipeline`) lives in your app. Every surface uses shadcn/ui CSS-variable utilities, so it inherits your theme — restyle the copied file freely.