ComponentsData display

Version history & diff

Revisions of a record: pick two, see what changed and restore an older one. Text diffs highlight changed words inside changed lines (jsdiff), side by side or unified, with collapsed unchanged runs and change navigation. Records diff field by field with locale formatting.

jsdiff (diff) + listbox pattern components/version-history.tsx, styles/data.csstheme · material · accent · density · font

Select two versions to compare.

  • v4 · Pricing and allergensCurrentİlker Şahin · 11/10/26, 9:12 AMUpdated reprint cost, added allergens and staff training.After
  • v3PublishedMeltem Öz · 11/8/26, 4:40 PMBefore
  • v2Autosaveİlker Şahin · 11/7/26, 11:05 AM
  • v1 · Outlineİlker Şahin · 11/5/26, 8:30 AM

v3v4 · Pricing and allergens

Loading versions…

Installation

$ pnpm add @vamos-ui/react

The whole kit as one package — get updates by bumping the version. Add the styles to globals.css: @import "@vamos-ui/react/styles.css";

Usage

import { VersionHistory, DiffView, FieldDiff } from "@vamos-ui/react";

<VersionHistory
  versions={revisions}
  loadVersion={(id) => api.revision(id).then((r) => r.body)}
  onRestore={(id) => api.restore(postId, id)}
/>

<DiffView before={a} after={b} mode="split" />
<FieldDiff before={v1} after={v2} fields={[{ key: "amount", label: "Amount", format: "currency" }]} />

Colour is never the only signal: +/− gutters, <ins>/<del> and screen-reader text ("Added line"). Diff panels are surface-2 and never blurred in glass mode.

Examples

Word, character and line diff

mode="split" puts before at the start side; granularity controls the in-line highlights.

3 additions, 3 deletions
Removed line: Vamos builds websites and panels for restaurants, clinics and agencies.
Removed line: Our team is based in Istanbul and works with clients across Europe.
Removed line: Projects start at $4,500 and launch in six weeks.
Added line: Vamos builds fast, accessible websites and admin panels for restaurants, clinics and agencies.
Added line: Our team is based in Istanbul and works with clients across Europe and the Gulf.
Added line: Projects start at $4,500 and launch in four to six weeks.

Record changes (CRM quote)

Values use the field's format; long text fields (type="text-long") get a word diff.

FieldQuote v2 · Nov 3Quote v3 · Nov 9
AmountChanged$48,500.00$52,000.00
DiscountChanged15%12%
StageChangedProposalNegotiation
OwnerChangedDaniel BrooksAyşe Kaya
SeatsChanged4045
SSO includedChangedNoYes
TermsChanged
Removed line: Annual billing, net 30. Price valid for 30 days.
Added line: Annual billing, net 45. Price locked for 12 months if signed by Dec 15.

Long document, collapsed hunks (HR policy)

context sets the unchanged lines kept around each change. Focus the diff and press n / p to jump between changes.

4 additions, 3 deletions
1. Employees accrue 1.75 days of paid leave per month.
2. Leave requests are approved by the direct manager.
Removed line: 3. Unused leave carries over until March 31.
Added line: 3. Unused leave carries over until April 30.
4. Sick leave requires a doctor's note after 2 days.
5. Remote work is allowed up to 3 days per week.
17. Leave requests are approved by the direct manager.
18. Unused leave carries over until March 31.
Removed line: 19. Sick leave requires a doctor's note after 2 days.
Added line: 19. Sick leave requires a doctor's note after 3 days.
20. Remote work is allowed up to 3 days per week.
21. Employees accrue 1.75 days of paid leave per month.
40. Remote work is allowed up to 3 days per week.
41. Employees accrue 1.75 days of paid leave per month.
Removed line: 42. Leave requests are approved by the direct manager.
Added line: 42. Remote work is allowed up to 4 days per week.
Added line: 42a. Work from abroad is allowed for 20 days a year.
43. Unused leave carries over until March 31.
44. Sick leave requires a doctor's note after 2 days.

API

VersionHistory

PropTypeDefault
versions
Revisions (any order; shown newest first).
Version[]—
loadVersion
Content of one version: text → DiffView, record → FieldDiff. Cached per id.
(id) => string | Record<string, unknown> | Promise<…>—
compare / defaultCompare / onCompareChange
The pair being compared; older is "before".
[string, string] / … / (pair) => void—
fields
Record versions: fields to compare.
FieldDiffField[]—
onRestore
"Restore this version" with a confirm dialog, then a success toast.
(id) => void | Promise<void>—
layout
List beside the diff, or stacked for a Sheet.
"page" | "panel""page"
defaultMode
Text diff layout.
"split" | "unified"page: "split", panel: "unified"
granularity
In-line highlights.
"word" | "char" | "line""word"
context
Unchanged lines kept around changes.
number3
labels
All built-in strings.
Partial<VersionHistoryLabels>—

Version

PropTypeDefault
id / createdAt
Identity and time.
string / ISO instant—
label / summary
"v12 · Pricing update" and a short note.
string—
author
Who saved it.
{ name; avatar? }—
kind
Badge.
"manual" | "autosave" | "published" | "system""manual"
current
The live version.
boolean—

DiffView

PropTypeDefault
before / after
Texts to compare.
string—
mode
Layout.
"unified" | "split""unified"
granularity
In-line highlights.
"word" | "char" | "line""word"
context
Collapsed context; Infinity shows all.
number3
beforeLabel / afterLabel
Column and region names.
string—
lineNumbers / toolbar / wrap
Gutters; summary + prev/next; wrap long lines.
booleantrue
actions
Extra toolbar content.
ReactNode—

FieldDiff

PropTypeDefault
before / after
Records to compare.
Record<string, unknown>—
fields
Fields in order. Default: every key, humanized.
{ key; label; format?; type?: "text" | "text-long" | "boolean" | "list" | "json"; render? }[]—
onlyChanges
Hide unchanged fields.
booleantrue
beforeLabel / afterLabel
Column headers.
string—

Helpers

PropTypeDefault
diffText(before, after, granularity)
The line model behind DiffView.
DiffLine[]—
diffRecords(a, b, fields?)
added / removed / changed / same per field.
{ key; change; before; after }[]—