# JSON diff viewer

A React component in [Beamline](https://beamline.io/)'s [Data & tables](https://beamline.io/components/data) category. Live demo: https://beamline.io/components/json-diff-viewer

Two versions of a JSON value compared as one tree: added keys marked +, removed ones struck through with −, changed values read old → new, unchanged keys folded into a count you can open; array items are matched by their id (not their place) so a reorder is not a hundred changes, a summary counts each kind, and the next and previous change are one key away; only the rows in view are drawn.

## Use it for

- Reviewing what changed in a configuration, a feature flag set, a record's history or a webhook payload between two versions.
- An audit log entry or an agent's proposed change to structured settings, before it is applied.

## Not for

- Text or code changes line by line ([file-diff](https://beamline.io/components/file-diff)).
- Rows of a table about to change ([diff-table](https://beamline.io/components/diff-table)).
- Reading one JSON value ([json-viewer](https://beamline.io/components/json-viewer)).

## Anatomy

- toolbar: the summary (+ added, − removed, ~ changed, in words for assistive tech), Only changes switch, previous / next change, Copy path
- tree: rows with a sign gutter (+ − ~), key, the value (changed: old struck → new), twisty for branches, a count of changes on a modified branch
- unchanged keys of a branch folded into one row (“12 unchanged”) that opens them
- footer: the active row's path

## Variants

- **0**: arrayKey: match array items by a field (default id when every item has one) or by place
- **1**: only changes: unchanged keys folded (default) or shown
- **2**: labels for the two sides: Before / After by default

## States

- no differences (said in words)
- a branch added or removed whole (one row, opens to its contents)
- a value whose type changed (object → string)
- large values (virtualised)

## Keyboard

- The tree is one tab stop: ↑ ↓ move, → opens, ← closes or goes to the parent, Home / End
- n and Shift+N (or the buttons) go to the next and previous change, opening the way to it
- p copies the active row's path

## Motion

Moving to a change scrolls it into view and its row lights once; opening a branch fades its rows in; the summary counts morph when the inputs change. Nothing moves at rest.

## Props

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `before / after` (required) | `unknown` | — | The two versions. |
| `arrayKey` | `string \| ((item: unknown) => string) \| false` | — | How array items are matched; false matches by place. |
| `onlyChanges / defaultOnlyChanges / onOnlyChangesChange` | `boolean` | — | Fold unchanged keys. Default true. |
| `labels` | `{ before?: string; after?: string }` | — | Names of the two sides, used in the summary and spoken values. |
| `rootName` | `string` | — | What paths start with. Default $. |
| `height / maxHeight` | `number \| "fill" / number` | — | As json-viewer. |
| `aria-label` (required) | `string` | — | What is compared: "Billing settings". |
| `className / classNames / style` | `` | — |  |

## Dependencies

`@tanstack/react-virtual`, `lucide-react`

## Import

```tsx
import { JsonDiffViewer } from "@/components/json-diff-viewer/json-diff-viewer";
```

## Get it

JSON diff viewer is part of Beamline: 200+ components and 50+ complete screens for React that your coding agent (Claude Code, Codex, Cursor or any MCP client) installs into your app through Beamline's MCP server, as a ready-built package or as plain React source you can change. $49 launch price, one payment, no subscription, lifetime updates, one licence for your whole team. [Get Beamline](https://beamline.io/checkout?pack=complete) · [Connect your agent](https://beamline.io/connect)

## More in Data & tables

- [Event calendar](https://beamline.io/components/event-calendar): A schedule of events by day, week or month: events that overlap sit side by side, drag one to another time or day or pull its bottom edge to change its…
- [Kanban board](https://beamline.io/components/kanban-board): Work as cards in columns by stage: drag a card (or lift it with Space and walk it with the arrows) to another column or place, the cards around it make…
- [Data grid](https://beamline.io/components/data-grid): Virtualised grid for thousands of rows: multi-sort, search and value filters, resizable and pinnable columns, range selection, inline edit, footer…
- [Pivot table](https://beamline.io/components/pivot-table): Records summed up by the fields people choose: rows grouped by one or more fields that fold open level by level, columns split by another, one or more…
- [Query builder](https://beamline.io/components/query-builder): Conditions people build by hand to pick out records: each rule is a field, an operator that fits the field (contains, between, in the last N days, is any…
- [Log viewer](https://beamline.io/components/log-viewer): Log lines as they stream: it follows the newest line until you scroll up, then counts what arrived and brings you back in one click; filter by level with…
- [JSON viewer](https://beamline.io/components/json-viewer): A JSON value as a tree you can read and walk: branches open and close (one level, or all at once), closed ones preview what they hold, every value reads…
- [Import mapping](https://beamline.io/components/import-mapping): Map the columns of a file to the fields of one record type, see what every value becomes, then run the import and get an outcome for each row…
- [Diff table](https://beamline.io/components/diff-table): Proposed edits to a table before they happen: new rows green, removals struck through, changed cells old → new; each change can be left out and Apply…
- [Filter toolbar](https://beamline.io/components/filter-toolbar): The filters on a list kept in view: chips that remove themselves, Add filter with fields and their values, Clear all, and room for search or view controls.
- [Table](https://beamline.io/components/table): A plain, styled HTML table for small static data: header, body, footer, caption, numeric cells, three densities and a sticky header.
