Installation
npx shadcn@latest add @assistant-ui/diff-viewerThe @assistant-ui namespace resolves the Radix or Base UI flavor from your project's style through the style-aware registry entry in components.json. Without that entry, add by direct URL instead:
npx shadcn@latest add https://r.assistant-ui.com/base/diff-viewer.jsonMain Component
npm install @assistant-ui/react-markdown class-variance-authority diff parse-diffUsage
import { DiffViewer } from "@/components/ui/diff-viewer";
// With a unified diff patch
<DiffViewer patch={diffString} />
// With file comparison
<DiffViewer
oldFile={{ content: "old content", name: "file.txt" }}
newFile={{ content: "new content", name: "file.txt" }}
/>As Markdown Language Override
Integrate with MarkdownTextPrimitive to render diff code blocks:
import { DiffViewer } from "@/components/ui/diff-viewer";
const MarkdownTextImpl = () => {
return (
<MarkdownTextPrimitive
remarkPlugins={[remarkGfm]}
className="aui-md"
components={defaultComponents}
componentsByLanguage={{
diff: {
SyntaxHighlighter: ({ code }) => <DiffViewer patch={code} />
},
}}
/>
);
};
export const MarkdownText = memo(MarkdownTextImpl);Examples
Unified View
Shows all changes in a single column with +/- indicators. This is the default mode.
<DiffViewer patch={diffString} viewMode="unified" />Split View
Shows old content on the left, new content on the right side-by-side.
<DiffViewer patch={diffString} viewMode="split" />Interactive Mode Toggle
Variants
Sizes
Theming
Changed lines carry a 2px gutter rule and a faint fill; the diff hue otherwise appears only on the +/- markers and the header stats, while code stays in ink. Override the CSS variables to retheme:
[data-slot="diff-viewer"] {
--diff-add-bg: color-mix(in oklab, var(--color-green-500) 8%, transparent);
--diff-add-rule: var(--color-green-500);
--diff-add-text: var(--color-green-600);
--diff-add-text-dark: var(--color-green-400);
--diff-del-bg: color-mix(in oklab, var(--color-red-500) 8%, transparent);
--diff-del-rule: var(--color-red-500);
--diff-del-text: var(--color-red-600);
--diff-del-text-dark: var(--color-red-400);
}| Variable | Description |
|---|---|
--diff-add-bg | Fill for added lines |
--diff-add-rule | Gutter rule for added lines |
--diff-add-text | Marker and stat color for additions (light mode) |
--diff-add-text-dark | Marker and stat color for additions (dark mode) |
--diff-del-bg | Fill for deleted lines |
--diff-del-rule | Gutter rule for deleted lines |
--diff-del-text | Marker and stat color for deletions (light mode) |
--diff-del-text-dark | Marker and stat color for deletions (dark mode) |
API Reference
DiffViewer
The main component for rendering diffs.
DiffViewerPropspatch?: stringUnified diff string (e.g., output from git diff).
code?: stringAlias for patch (for markdown integration).
oldFile?: { content: string; name?: string }Old file for direct comparison.
newFile?: { content: string; name?: string }New file for direct comparison.
viewMode: "unified" | "split"= "unified"Display mode for the diff.
variant: "default" | "ghost" | "muted"= "default"Visual style variant.
size: "sm" | "default" | "lg"= "default"Font size.
showLineNumbers: boolean= trueShow line numbers.
showIcon: boolean= falseShow file extension badge in header.
showStats: boolean= trueShow addition/deletion counts in header.
className?: stringAdditional CSS classes.
Composable API
| Component | Description |
|---|---|
DiffViewer | Main component that renders the diff. |
DiffViewerFile | Wrapper for each file in multi-file diffs. |
DiffViewerHeader | File name header with icon and stats. |
DiffViewerContent | Scrollable content area. |
DiffViewerLine | Individual line in unified mode. |
DiffViewerSplitLine | Side-by-side line pair in split mode. |
DiffViewerFileBadge | File extension badge (e.g., "TS"). |
DiffViewerStats | Addition/deletion count display. |
Style Variants (CVA)
| Export | Description |
|---|---|
diffViewerVariants | Styles for the root container. |
diffLineVariants | Background styles for diff lines. |
diffLineTextVariants | Text color styles for diff lines. |
import {
diffViewerVariants,
diffLineVariants,
diffLineTextVariants,
} from "@/components/ui/diff-viewer";
// Use variants directly
<div className={diffViewerVariants({ variant: "ghost", size: "sm" })}>
Custom diff container
</div>Utilities
| Export | Description |
|---|---|
parsePatch(patch) | Parse unified diff string into structured data. |
computeDiff(old, new) | Compute diff between two strings. |
ParsedLine | Type for a single diff line. |
ParsedFile | Type for a parsed file with lines and stats. |
SplitLinePair | Type for a side-by-side line pair. |
Styling
Data Attributes
Use data attributes for custom styling:
| Attribute | Values | Description |
|---|---|---|
data-slot | "diff-viewer", "diff-viewer-header", "diff-viewer-line", etc. | Component identification |
data-type | "add", "del", "normal", "empty" | Line type |
data-view-mode | "unified", "split" | Current view mode |
data-variant | "default", "ghost", "muted" | Current variant |
Custom CSS Example
[data-slot="diff-viewer"][data-view-mode="split"] {
/* Custom split view styles */
}
[data-slot="diff-viewer-line"][data-type="add"] {
/* Custom addition styles */
}
[data-slot="diff-viewer-line"][data-type="del"] {
/* Custom deletion styles */
}Related Components
- Markdown - Rich text rendering where diff viewer can be integrated
- Syntax Highlighting - Code highlighting for other languages