# CodeDiff

> Unified diff tuned for chat width: one foldable card per file, tinted add/delete rows, and a copy-safe gutter.

- Package: `fancy-ui-svelte` (Svelte 5 + Tailwind CSS v4)
- Category: AI Agents
- Tags: ai, agents, diff, code, review
- Docs: https://fancy-ui.rama.app/docs/components/code-diff
- Source: https://github.com/RamaHerbin/fancy-ui/tree/main/src/lib/fancy-ui/code-diff

## Import

```svelte
<script lang="ts">
  import { CodeDiff } from 'fancy-ui-svelte';
</script>
```

Setup (once per project): `npm install fancy-ui-svelte`, then add `@import "fancy-ui-svelte/tailwind.css";` after `@import "tailwindcss";` in your main CSS file. Full guide: https://fancy-ui.rama.app/llms.txt

React: `import { CodeDiff } from 'fancy-ui-react';` (same prop names; `class` becomes `className`, snippets become `ReactNode`).

## Props

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `diff` (required) | `string` | — | Raw unified diff text, headers and all; parsed on every change, so a patch still arriving can be handed over as it grows |
| `filename` | `string` | — | Header label when the patch names no file, or names exactly one |
| `lineNumbers` | `boolean` | `true` | Whether to show the old/new line-number gutters |
| `collapsed` | `boolean` | `false` | Whether the bodies are folded away (bindable). Set it and the whole patch folds; a click folds one file and writes back whether anything is left open |
| `maxLines` | `number` | `0` | Lines shown per file before the rest hide behind a "Show N more lines" button; 0 shows everything |
| `wrap` | `boolean` | `false` | Whether long lines wrap instead of scrolling sideways |
| `sound` | `boolean` | `false` | Plays open or close as a file folds, and open when clamped lines are revealed, once the user has enabled sound |

## Examples

### Basic Usage

```svelte
<script lang="ts">
	import { CodeDiff } from "fancy-ui-svelte";

	/** A two-hunk edit to one file: the shape an agent hands back after a fix. */
	const PATCH = [
		"diff --git a/src/lib/query.ts b/src/lib/query.ts",
		"index 8f2a1c4..b31e097 100644",
		"--- a/src/lib/query.ts",
		"+++ b/src/lib/query.ts",
		"@@ -12,6 +12,7 @@ export async function totalsByRegion(db: Db) {",
		"   const sql = compile(ast);",
		"-  const rows = await db.query(sql);",
		"-  return rows;",
		"+  const rows = await db.query(sql, { timeout: 5_000 });",
		"+  if (rows.length === 0) return [];",
		"+  return rows.map(normalise);",
		" }",
		" ",
		" function normalise(row: Row) {",
		"@@ -41,3 +42,3 @@ function normalise(row: Row) {",
		"   const region = row.region ?? UNASSIGNED;",
		"-  return { region, total: row.total };",
		"+  return { region, total: Number(row.total) };",
		" }",
		"",
	].join("\n");

	/** A move with an edit inside it, so the header has something to say. */
	const RENAME = [
		"diff --git a/src/lib/query.ts b/src/lib/db/totals.ts",
		"similarity index 94%",
		"rename from src/lib/query.ts",
		"rename to src/lib/db/totals.ts",
		"--- a/src/lib/query.ts",
		"+++ b/src/lib/db/totals.ts",
		"@@ -1,3 +1,3 @@",
		'-import { compile } from "./ast";',
		'+import { compile } from "../ast";',
		" ",
		' const UNASSIGNED = "Unassigned";',
		"",
	].join("\n");
</script>

<div class="flex w-full max-w-2xl flex-col gap-4">
	<CodeDiff sound diff={PATCH} />
	<CodeDiff sound diff={RENAME} />
</div>
```
