Prose diff

Pro

An agent's rewrite of a document (a knowledge page, a process description), shown word by word against the original. Each change can be accepted or rejected on its own; undecided changes show both versions. The result is reported as text once every change is decided. With readOnly it only shows what changed (between two published versions, say): no decisions.

Markdown

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/prose-diff

Brings in: button, diff, locale, utils · npm: lucide-react@^1.67.0

Usage

TSX · The example above
"use client"

import * as React from "react"
import { ProseDiff } from "@/components/prose-diff"

const original =
  "Customers are routed to a data region by partner tier for partner accounts and by billing country for everyone else. The platform team reviews routing every quarter."
const revised =
  "Customers are routed to a data region by the region column for every account. The platform team reviews routing every quarter."

export default function Example() {
  const [result, setResult] = React.useState<string | null>(null)
  return (
    <div className="flex max-w-xl flex-col gap-3">
      <ProseDiff original={original} revised={revised} onResolve={setResult} />
      {result && <p className="text-sm text-muted-foreground">Saved: {result}</p>}
    </div>
  )
}

<ProseDiff>

PropTypeDefaultDescription
originalrequiredstring—The text before the rewrite.
revisedrequiredstring—The agent's rewrite.
onResolve((text: string) => void) | undefined—Called with the final text when every change has a decision.
readOnlyboolean | undefinedfalseShow the changes without accept and reject: the header counts them, and `onResolve` is never called.
classNamestring | undefined—Extra classes for the outer element.

Strings

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

KeyEnglish
suggestedChangesSuggested changes
decided{decided} of {total} decided
rejectAllReject all
acceptAllAccept all
removedremoved:
addedadded:
acceptChangeAccept this change
rejectChangeReject this change
changesChanges
changeCount{ one: "{count} change", other: "{count} changes" }