# Diff View
Source: https://ui.spencerwueste.com/docs/components/diff-view
Markdown: https://ui.spencerwueste.com/llm/components/diff-view.md

> Unified diff with line numbers, per-hunk actions, and accepted or rejected states for agent-proposed patches.

> Live preview: https://ui.spencerwueste.com/docs/components/diff-view (demo source: `src/demos/diff-view-demo.tsx`)

## Installation

```bash
npx shadcn@latest add https://ui.spencerwueste.com/r/diff-view.json
```

Manual install dependencies: `@heroicons-animated/react motion`

Registry JSON: https://ui.spencerwueste.com/r/diff-view.json

Ships with `lib/diff.ts`, a small LCS line diff. Swap it for the `diff` package when you need word-level diffs or very large files.

## Usage

```tsx
import { DiffHeader, DiffHunkView, DiffView } from "@/components/pandacoderz-ui/diff-view";
import { computeDiff, diffStats } from "@/lib/diff";
```

```tsx
const hunks = computeDiff(before, after);
const { additions, deletions } = diffStats(hunks);

<DiffView>
  <DiffHeader path="src/app.tsx" additions={additions} deletions={deletions} />
  {hunks.map((hunk) => (
    <DiffHunkView
      key={hunk.id}
      hunk={hunk}
      decision={decisions[hunk.id]}
      actions={<AcceptRejectButtons onDecide={(d) => decide(hunk.id, d)} />}
    />
  ))}
</DiffView>
```

If your API already returns hunks, skip `computeDiff` and pass them straight in. The shape is `{ id, oldStart, oldLines, newStart, newLines, lines: { type, text, oldLine?, newLine? }[] }`.

## API Reference

### DiffHeader

| Prop | Type | Description |
| --- | --- | --- |
| `path` | `string` | File path shown in monospace. |
| `additions` / `deletions` | `number` | Renders the +/− stats. |
| `children` | `ReactNode` | Right-aligned actions. |

### DiffHunkView

| Prop | Type | Description |
| --- | --- | --- |
| `hunk` | `DiffHunk` | The hunk to render. |
| `actions` | `ReactNode` | Shown in the hunk header until a decision is made. |
| `decision` | `"accepted" \| "rejected"` | Replaces actions with a badge; rejected hunks dim. |
| `lineNumbers` | `boolean` | Default `true`. |
