React Native Diffs

Diff library for React Native, powered by MarkdownView.

Installation

npm install react-native-diffs react-native-nitro-modules

Usage

import { DiffsView } from 'react-native-diffs';

const diff = `\`\`\`diff
@@ -11,7 +11,7 @@ export default function Home() {
 <div>
-  <h2>Design Engineer</h2>
+  <h2>Designer</h2>
 </div>
\`\`\``;

export default function App() {
  return (
    <DiffsView
      content={diff}
      colorScheme="dark"
      style={{ flex: 1 }}
    />
  );
}

Diff formats

Content can be a fenced ```diff ``` or ```patch ``` code block, or a raw unified diff string — MarkdownView auto-detects and renders it as a styled diff view with hunk headers, line numbers, and inline change highlighting.

You can also include multiple fenced diff blocks in a single content string to render them all in one scrollable view.

Examples

Custom dark theme

import { DiffsView, type Theme } from 'react-native-diffs';

const theme: Theme = {
  fonts: {
    codeSize: 15,
  },
  colors: {
    body: '#E1E2E5',
    code: '#D4D4D8',
    codeBackground: '#18181B',
    highlight: '#60A5FA',
    emphasis: '#A1A1AA',
    selectionTint: '#34D399',
  },
  diff: {
    displayMode: 'unified',
    changeHighlightStyle: 'both',
    backgroundColor: '#000000',
    gutterBackground: '#0A0A0A',
    gutterText: '#52525B',
    addedLineBackground: '#22C55E33',
    removedLineBackground: '#DC262620',
    addedHighlightBackground: '#4ADE8066',
    removedHighlightBackground: '#DC262650',
    hunkHeaderBackground: '#27272A',
    hunkHeaderText: '#71717A',
    separatorColor: '#27272A',
    borderWidth: 0,
  },
};

<DiffsView
  content={diff}
  colorScheme="dark"
  showsBlockHeaders={false}
  theme={theme}
  style={{ flex: 1, backgroundColor: '#000000' }}
/>

Props

PropTypeRequiredDescription
contentstringYesMarkdown or diff content to render
colorSchemestringYesColor scheme ("dark" or "light")
contentInsetContentInsetNoScroll view content inset { top, bottom }
showsBlockHeadersbooleanNoShow code/diff block headers with copy button (default true)
themeThemeNoCustom theme configuration
customMenuItemsCustomMenuItem[]NoExtra items appended to the text-selection menu on code/diff blocks
onCustomMenuAction(event: CustomMenuEvent) => voidNoFires when a custom menu item is tapped. Must be wrapped as { f: handler } (see below)
onLineSelection(info?: LineSelectionInfo) => voidNoEnables line selection mode; fires continuously as the user drags. Wrap as { f: handler }
onLineSelectionEnd(info?: LineSelectionInfo) => voidNoFires once when the selection gesture settles (tap release / drag release). Wrap as { f: handler }. Setting only this still enables line selection.

Callback wrapping

Nitro view-prop callbacks cross the bridge as a reference-tracked wrapper, so functions must be passed as { f: handler } rather than bare functions:

<DiffsView
  onCustomMenuAction={{ f: (event) => console.log(event) }}
  onLineSelectionEnd={{ f: (info) => console.log(info) }}
/>

Custom menu items

Long-press a code or diff block to bring up the text-selection menu. Items in customMenuItems are appended after the system actions (Copy, Select All, Share). systemImage accepts any SF Symbol name.

<DiffsView
  content={content}
  customMenuItems={[
    { id: 'explain', title: 'Explain', systemImage: 'lightbulb' },
    { id: 'apply', title: 'Apply', systemImage: 'checkmark.circle' },
  ]}
  onCustomMenuAction={{
    f: ({ itemId, text, startLine, endLine }) => {
      console.log(itemId, text, startLine, endLine);
    },
  }}
/>

Line selection

Providing onLineSelection or onLineSelectionEnd switches code and diff blocks from text selection to line selection: tap to select a single line, or long-press-and-drag to select a range.

  • onLineSelection fires on every range change — use it for live visual feedback.
  • onLineSelectionEnd fires exactly once per interaction, when the user lifts their finger — use it for actions like showing a contextual button. You can set it on its own.

Customize the highlight with theme.colors.lineSelectionBackground.

<DiffsView
  content={content}
  theme={{ colors: { lineSelectionBackground: '#60A5FA33' } }}
  onLineSelectionEnd={{
    f: (info) => {
      if (!info) return;
      console.log(`lines ${info.startLine}-${info.endLine}`, info.contents);
    },
  }}
/>

Theming

Pass a theme prop to customize the appearance. All fields are optional — only override what you need. Colors are hex strings with optional alpha (e.g. "#FF0000" or "#FF000080"). Colors are rendered in the Display P3 color space for wider gamut on supported devices.

Theme Structure

ThemeFonts

PropertyTypeDescription
bodySizenumberBody text font size
codeSizenumberCode block font size
codeInlineSizenumberInline code font size
titleSizenumberTitle font size
largeTitleSizenumberLarge title font size
footnoteSizenumberFootnote font size

ThemeColors

PropertyTypeDescription
bodystringMain text color
highlightstringHighlight/accent color
emphasisstringEmphasis color
codestringCode text color
codeBackgroundstringCode block background color
selectionTintstringText selection tint color
selectionBackgroundstringText selection fill. Defaults to selectionTint at 20% alpha
lineSelectionBackgroundstringHighlight color used in line selection mode

ThemeSpacings

PropertyTypeDescription
finalnumberFinal spacing (default 16)
generalnumberGeneral inter-block spacing (default 8)
listnumberList item spacing (default 8)
cellnumberCell spacing (default 32)

ThemeSizes

PropertyTypeDescription
bulletnumberBullet point size (default 4)

ThemeTable

PropertyTypeDescription
cornerRadiusnumberTable corner radius (default 8)
borderWidthnumberTable border width (default 1)
borderColorstringBorder color
headerBackgroundColorstringTable header background
cellBackgroundColorstringCell background
stripeCellBackgroundColorstringAlternating row background

ThemeImage

PropertyTypeDescription
cornerRadiusnumberImage corner radius (default 4)
maxWidthFractionnumberMax width as fraction of container (default 1.0)
placeholderColorstringLoading placeholder color

ThemeDiff

PropertyTypeDescription
displayModeDiffDisplayMode'unified' or 'sideBySide'
scrollBehaviorDiffScrollBehavior'horizontalOnly' or 'bothAxes'
changeHighlightStyleDiffChangeHighlightStyle'lineOnly', 'inlineOnly', or 'both'
lineNumberStyleDiffLineNumberStyle'dual' (separate old/new columns, default) or 'single' (unified column). Unified mode only
showsChangeMarkersbooleanShow the +/− gutter column (default true). Combine 'single' + false for a minimal gutter
contextCollapseThresholdnumberLines before context is collapsed (default 8)
visibleContextLinesnumberVisible context lines around changes (default 2)
gutterBackgroundstringGutter background color
gutterTextstringGutter text color
backgroundColorstringOverall diff background
addedLineBackgroundstringAdded line row color
removedLineBackgroundstringRemoved line row color
addedHighlightBackgroundstringWord-level added highlight
removedHighlightBackgroundstringWord-level removed highlight
hunkHeaderBackgroundstringHunk header background
hunkHeaderTextstringHunk header text color
fileHeaderBackgroundstringFile header background
fileHeaderTextstringFile header text color
fileMetadataTextstringFile metadata text color
separatorColorstringSeparator color
borderWidthnumberDiff border width (set 0 to remove)
borderColorstringDiff border color

Contributing

License

MIT