# Code review

> A pull request review in one card: file tabs with viewed progress, a syntax tinted diff with a comment mark on every line, threads that fold away when resolved, suggestions that rewrite the diff in place, and an approve button that morphs into the approved state.

- Type: Block
- Page: https://uiarc.dev/components/blocks/code-review
- Markdown: https://uiarc.dev/components/blocks/code-review/markdown

- Access: Arc Pro
- Registry id: `code-review`
- Source file: `registry/blocks/code-review/code-review.tsx`
- Built from: Tabs, Code block, Comment thread, Checkbox, Button, Animated counter
- Keywords: code review, pull request, diff viewer, suggested change, line comments, approve, request changes, file tree, github review

Use this for code review inside a developer tool. Load diffs and comments from your git provider; actions in the preview are local.

## When to use

- Reviewing a pull request with line comments and suggestions.
- An internal tool that approves generated code changes file by file.
- A review queue where viewed state and pending comments matter.

## When not to use

- Showing one read-only snippet; use the code block component.
- Watching an agent write code live; use agent-run.
- Comparing two text documents without review actions.

## Installation

Code review is part of Arc Pro. The live preview is public; the source and install command need Pro.

### CLI with a Pro token

1. Create a token in your account and set it in the environment (or `.env.local`). Never commit it.

```bash
export ARC_PRO_TOKEN=arc_pro_...
```

2. Add the Pro registry to `components.json`:

```json
{
  "registries": {
    "@uiarc": "https://uiarc.dev/r/{name}.json",
    "@uiarc-pro": {
      "url": "https://uiarc.dev/r/pro/{name}.json",
      "headers": {
        "Authorization": "Bearer ${ARC_PRO_TOKEN}"
      }
    }
  }
}
```

3. Install:

```bash
npx shadcn@latest add @uiarc-pro/code-review
```

### Manual

Signed-in Pro members can copy the source from the Manual tab on the docs page.

- Plans: https://uiarc.dev/pricing
- Create a Pro token: https://uiarc.dev/account#pro-access
- Setup guide: https://uiarc.dev/docs/ai#pro-access

## Usage

```tsx
import { CodeReview } from "@/components/arc/blocks/code-review/code-review";

export function PullRequestReview({ pr, files, threads }: ReviewData) {
  return (
    <CodeReview
      pull={pr}
      files={files}
      threads={threads}
      onApplySuggestion={(thread, lines) => api.commitSuggestion(pr.number, thread.id)}
      onSubmitReview={({ event, body, comments }) => api.submitReview(pr.number, { event, body, comments })}
    />
  );
}
```

## API reference

### CodeReview

A pull request review in one card. File tabs show which files are viewed and which have open conversations, with a progress bar beside them; the selected file shows its path, diffstat and a Viewed checkbox above a syntax tinted unified diff. Hover a line, or focus its line number, and an add comment mark appears in the gutter; press it to open a comment box under the line, optionally with a suggested change. Threads carry comments, an optional suggestion with Apply, Reply and Resolve. Applying a suggestion rewrites the diff in place and folds the thread to one line; Approve submits the review with your pending comments and morphs into an Approved state.

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `pull` | `PullRequest` | `sample pull request` | Title, number, repository, head and base branches, commit count, author and when it was opened. Shown in the header. |
| `files` | `ReviewFile[]` | `5 sample files` | Changed files, shown as tabs in this order. Each has an id, path, language ("ts" or "md"), status ("added" or "modified") and diff lines. Lines are hunk headers with oldStart and newStart, followed by ctx, add and del lines; line numbers are derived, so edits renumber correctly. |
| `threads` | `ReviewThread[]` | `2 sample threads` | Existing conversations. Each is anchored under a line id, carries a label such as Line 9, its comments, whether it is resolved and an optional suggestion with the line ids it replaces. Resolved threads start folded. |
| `viewer` | `Person` | `Olivia Bennett` | The person reviewing. New comments and replies are written as them. |
| `defaultFileId` | `string` | `first file with an open conversation` | The file shown first. |
| `onComment` | `(thread: ReviewThread) => void` | – | Called when a line comment is added. The thread is pending until the review is approved. |
| `onReply` | `(threadId: string, comment: ReviewComment) => void` | – | Called when a reply is posted in a thread. |
| `onResolve` | `(threadId: string, resolved: boolean) => void` | – | Called when a conversation is resolved or reopened. Applying a suggestion resolves its thread. |
| `onApplySuggestion` | `(thread: ReviewThread, lines: DiffLine[]) => void` | – | Called after a suggestion is applied, with the thread and the file's new diff lines. Commit the change on your server here. |
| `onViewedChange` | `(fileId: string, viewed: boolean) => void` | – | Called when a file is marked viewed or not viewed. |
| `onSubmitReview` | `(review: { event: "approve"; body: string; comments: ReviewThread[] }) => void \| Promise<void>` | – | Sends the approval with its pending comments. While a returned promise is pending the button shows progress; a rejected promise shows a Try again state. Without a handler the preview simulates a short submit. |
| `className` | `string` | – | Class on the root element. |

## Keyboard interactions

| Keys | Action |
| --- | --- |
| Tab | Moves through the approve button, the file tabs, the Viewed checkbox, one line number per file and the thread actions. |
| Arrow Left / Arrow Right, Home / End | In the file tabs, selects the previous, next, first or last file. |
| Arrow Up / Arrow Down, Home / End | On a line number, moves to the previous, next, first or last line. |
| Enter / Space | On a line number, opens or closes the comment box for that line. |
| Cmd/Ctrl + Enter | Posts the comment or reply you are typing. |
| Escape | Closes the comment box or reply and returns focus to the line number. |

## Accessibility

- The files are a tablist with roving focus; each tab reports its path, viewed state and open conversations, and controls the diff panel.
- Each line number is a button named for the line, such as Comment on added line 9. Added and removed lines carry visually hidden prefixes, so the diff reads correctly without color.
- Viewed is a role="checkbox"; Suggest a change is a pressed toggle; a folded thread is a button with aria-expanded that opens it again.
- Adding comments, applying suggestions, resolving, marking files viewed and approving are announced in a polite live region.
- Reduced motion applies every change at once while keeping focus and announcements.

## Motion

- Comment boxes and threads open as bands in the flow of the diff, height and opacity on the smooth spring, so the lines below slide instead of jumping.
- Posting a comment keeps its band: the box crossfades into the new thread while the height springs between them.
- Applying a suggestion folds the old line out while the new line grows in at the same place, then the new line settles from a stronger tint to the normal added color. The Apply button morphs to Applied and the thread folds a beat later.
- A resolved thread folds to a one line summary: the summary fades in at the top while the band springs to its new height, once, with no chained springs.
- The add comment mark scales in on the gutter edge with a short delay, so a passing pointer does not light up every line.
- The tab highlight slides between files on the morph spring and the diff crossfades with a short slide in the direction of travel; progress fills on the smooth spring with a rolling counter.
- Approve shows progress, then morphs its label and width into Approved and a status band opens under the header.

## Responsive behavior

- The header stacks and the progress bar moves above the tabs below 560px of card width; tabs scroll sideways when they do not fit.
- Below 560px one line number column remains. Long lines never wrap: the diff scrolls sideways with the line numbers pinned, and threads stay the width of the card.

## Performance

- Rows are memoized and only animate when they enter or leave; hover and the add comment mark are CSS only.
- Heights animate only on a real change of content, never on every resize.
- Keep single files to a few hundred lines, or split long files into hunks.

## Notes for AI

- Choose this for a code review inside a developer tool. Load the diff from your git provider and map hunks to hunk lines with oldStart and newStart; everything else is derived.
- Anchor threads by line id, not by line number, so they stay attached after suggestions rewrite the file.
- Suggestions only replace new side lines: added lines are swapped, unchanged lines become deletions followed by the new lines. Keep the commit on your server; the block updates the diff optimistically.
- The card grows with its content and only the diff scrolls sideways. In a centered layout, pin it to the top if height changes should not move it.

## Related

- [Agent run](https://uiarc.dev/components/blocks/agent-run/markdown): A single card that follows one AI coding agent through a task: steps stream in with the live one shimmering, tool calls open in place, and the agent stops on a two-file diff for you to approve or send back before it writes. When the run ends, the steps fold into one line and a result shows the files changed, the checks that passed and a pull request button.

## Guidance for AI tools

Blocks are complete, self-contained screens with sample data. Replace the sample data and connect the callbacks described above. Follow the declared prop types and do not invent props. Keep keyboard access, reduced motion support, and both light and dark themes intact when adapting it.

Full library index: https://uiarc.dev/llms.txt
