DiffView component
DiffView compares two texts line by line and highlights the words that changed inside a changed line: two revisions of a post, two versions of a setting, a piece of code. It shows the texts side by side or one under the other, and folds long unchanged stretches behind a button. It has no dependencies, and the comparison itself is also exported as plain functions a server can call.
Playground
Change a prop on the right and the preview updates. Switch to Code to copy what you see.
Comparing two texts
Give it before and after. The default is split, two columns with line numbers; unified puts removed lines above added ones in one column. context sets how many unchanged lines stay visible around each change (3 by default). Longer unchanged runs fold behind a Show N unchanged lines button, and context={Infinity} shows everything.
<DiffView before={oldBody} after={newBody} beforeTitle="12 March" afterTitle="Current" />
<DiffView before={a} after={b} mode="unified" context={Infinity} monospace={false} />Ignoring whitespace and wrapping
ignoreWhitespace treats lines that differ only in spaces and tabs as unchanged. wrapLines (on by default) wraps long lines; turn it off to scroll sideways, which suits code. monospace={false} uses the surrounding font, which suits prose.
<DiffView before={configA} after={configB} ignoreWhitespace wrapLines={false} />Without the component
diffLines, diffWords and diffStats are plain functions, and the oks-ui/diff-view entry is not marked use client, so a Server Component or an API route can use them, for example to show 3 added, 1 removed in a list of revisions.
import { diffLines, diffStats } from "oks-ui/diff-view";
const { added, removed } = diffStats(diffLines(oldBody, newBody));Props
The full public API for DiffView. Every prop is stable and intentionally typed.
Data
| Prop | Type | Default | Description |
|---|---|---|---|
| before / after | string | — | The older and the newer text. |
before / after
string
default: —
The older and the newer text.
Appearance
| Prop | Type | Default | Description |
|---|---|---|---|
| mode | "split" | "unified" | split | Side by side, or one column with removed lines above added ones. |
| showLineNumbers | boolean | true | The line-number columns. |
| wrapLines | boolean | true | Wraps long lines. false scrolls sideways. |
| monospace | boolean | true | A fixed-width font, for code. false uses the surrounding font, for prose. |
| classNames | Partial<Record<slot, string>> | — | Class per part: base, summary, table, row, lineNumber, content, fold. |
mode
"split" | "unified"
default: split
Side by side, or one column with removed lines above added ones.
showLineNumbers
boolean
default: true
The line-number columns.
wrapLines
boolean
default: true
Wraps long lines. false scrolls sideways.
monospace
boolean
default: true
A fixed-width font, for code. false uses the surrounding font, for prose.
classNames
Partial<Record<slot, string>>
default: —
Class per part: base, summary, table, row, lineNumber, content, fold.
Behavior & states
| Prop | Type | Default | Description |
|---|---|---|---|
| context | number | 3 | Unchanged lines shown around each change. Longer unchanged runs fold behind a button. Infinity shows every line. |
| wordDiff | boolean | true | Highlights the changed words inside a replaced line. |
| ignoreWhitespace | boolean | false | Lines that differ only in spaces and tabs count as unchanged. |
context
number
default: 3
Unchanged lines shown around each change. Longer unchanged runs fold behind a button. Infinity shows every line.
wordDiff
boolean
default: true
Highlights the changed words inside a replaced line.
ignoreWhitespace
boolean
default: false
Lines that differ only in spaces and tabs count as unchanged.
Content
| Prop | Type | Default | Description |
|---|---|---|---|
| showSummary | boolean | true | The line above the table (2 lines added, 1 removed). |
| beforeTitle / afterTitle | ReactNode | Before / After | Column titles, such as a revision name or a date. |
| labels | Partial<DiffViewLabels> | English | The text DiffView adds: removed, added, showUnchanged(count), summary(added, removed), noChanges, before, after. Also set app-wide with LocaleProvider. |
showSummary
boolean
default: true
The line above the table (2 lines added, 1 removed).
beforeTitle / afterTitle
ReactNode
default: Before / After
Column titles, such as a revision name or a date.
labels
Partial<DiffViewLabels>
default: English
The text DiffView adds: removed, added, showUnchanged(count), summary(added, removed), noChanges, before, after. Also set app-wide with LocaleProvider.
Accessibility
- A real table with column headers, named by its summary (2 lines added, 1 removed). The line-number columns have hidden header text.
- Each removed or added line starts with hidden text (Removed:, Added:), so a change is not shown by colour alone. Changed words are real ins and del elements, and removed words are also struck through.
- The tints sit under normal text and keep 4.5:1 contrast in light and dark themes.
- A fold is a real button; opening it shows the lines in place.
Best practices
- Give the two columns meaningful titles (a revision name or date) with beforeTitle and afterTitle.
- Very large and very different texts fall back to one removed and one added block instead of an exact comparison, so the page stays fast.
- For prose, set monospace to false and keep wrapLines on.
- Translate the text DiffView adds with the labels prop or LocaleProvider.