Skip to content
Tier

Change diff

Pro

The change as files: one tab per file, each named by the thing it is (a field, a layout) as well as its path, with a unified diff that highlights the exact words that changed inside a line.

Its strings are overridden under changeDiff in LocaleProvider's strings.

Markdown
Version 5.2.0· other versions

This page is for 5.2.0, the current release. An earlier release’s page is the Markdown that release published, so the docs match the version you have installed (candor-lock.json records it).

Not in the docs of 1.3.0, 1.4.0, 1.5.0, 1.5.1, 1.6.0, 1.7.0, 1.8.0, 1.8.1, 1.9.0, 1.9.1, 2.0.0, 2.1.0, 2.2.0, 2.3.0, 2.4.0, 2.5.0, 2.5.1, 2.6.0, 2.6.1, 2.6.2, 2.7.0, 2.8.0, 2.9.0 and 2.10.0: the page came later, or had another name then.

Docs pages weren’t kept for 1.0.0, 1.0.1, 1.1.0, 1.1.1, 1.2.0 and 1.2.1: they are kept from 1.3.0 on, and before that only llms.txt was published.

Preview

Loading the preview

Install

With the Candor CLI

First time? Get started sets up the registry and theme. Or with shadcn directly: npx shadcn@latest add @candor/change-diff

Brings in: bidi, entity-chip, locale, tokens, work, utils · npm: @base-ui/react@^1.9.0, lucide-react@^1.67.0

Usage

TSX · The example above
"use client"

import type { FileDiff } from "@/lib/candor/work"
import { ChangeDiff } from "@/components/candor/change-diff"

const files: FileDiff[] = [
  {
    path: "db/migrations/0142_add_customer_region.sql",
    entity: { kind: "migration", name: "0142_add_customer_region", label: "Add customers.region" },
    change: "create",
    language: "sql",
    hunks: [
      {
        lines: [
          { kind: "add", text: "CREATE TYPE region AS ENUM ('us', 'eu', 'apac', 'other');", newNo: 1 },
          { kind: "add", text: "ALTER TABLE customers ADD COLUMN region region;", newNo: 2 },
          { kind: "add", text: "CREATE INDEX customers_region_idx ON customers (region);", newNo: 3 },
        ],
      },
    ],
  },
  {
    path: "web/src/customers/CustomerHeader.tsx",
    entity: { kind: "component", name: "web/src/customers/CustomerHeader.tsx", label: "CustomerHeader" },
    change: "update",
    language: "tsx",
    hunks: [
      {
        header: "@@ function CustomerHeader @@",
        lines: [
          { kind: "context", text: '      <Fact label="Plan" value={customer.plan} />', oldNo: 43, newNo: 43 },
          { kind: "remove", text: '      <Fact label="Partner tier" value={customer.partnerTierOld} />', oldNo: 44 },
          { kind: "add", text: '      <Fact label="Region" value={regionLabel(customer.region)} />', newNo: 44 },
          { kind: "context", text: "    </dl>", oldNo: 45, newNo: 45 },
        ],
      },
    ],
  },
]

export default function Example() {
  return <ChangeDiff className="max-w-3xl" files={files} />
}

<ChangeDiff>

PropTypeDefaultDescription
filesrequiredFileDiff[]—The changed files, one tab each.
classNamestring | undefined—Extra classes for the outer element.

Strings

The fixed words, in English by default. Change any of them under changeDiff in <LocaleProvider strings={{ … }}>; the table is exported as changeDiffStrings.

KeyEnglish
labelChanges
files{ one: "{count} file", other: "{count} files" }
fileTabsFiles
createNew
updateChanged
deleteDeleted
addedAdded:
removedRemoved:

Motion

MomentFamilyWhat it does
tinttintA file tab's text colour changes when the pointer is over it, and its background and shadow change when the person selects it; a ring fades in on keyboard focus.

Set with --cd-motion-change-diff-<moment>-* in your brand file; the families are in the design reference.

Types from other items

The props above take these. Each is defined by another item; import it from the path shown.

FileDiff from @/lib/candor/work
{ path: string; /** What the file is, e.g. a field or a layout. */ entity?: EntityRef | undefined; change: "create" | "update" | "delete"; /** e.g. "xml", "ts", "python"; shown as a label. */ language?: string | undefined; hunks: DiffHunk[]; }
EntityRef from @/lib/candor/chat
{ kind: EntityKind; /** The identifier, e.g. "orders.status" or "billing.invoice.due_date". */ name: string; /** A friendlier label when there is one, e.g. "Region". */ label?: string | undefined; /** Where it lives, when more than one place is in scope, e.g. "Shop staging". */ location?: string | undefined; }
DiffHunk from @/lib/candor/work
{ header?: string | undefined; lines: DiffLine[] }